1 /*
2 * The catalog B-tree file functions
3 *
4 * Copyright (C) 2009-2021, 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_btree_node.h"
27 #include "libfshfs_btree_node_record.h"
28 #include "libfshfs_catalog_btree_file.h"
29 #include "libfshfs_catalog_btree_key.h"
30 #include "libfshfs_definitions.h"
31 #include "libfshfs_directory_entry.h"
32 #include "libfshfs_directory_record.h"
33 #include "libfshfs_file_record.h"
34 #include "libfshfs_libbfio.h"
35 #include "libfshfs_libcdata.h"
36 #include "libfshfs_libcerror.h"
37 #include "libfshfs_libcnotify.h"
38 #include "libfshfs_libuna.h"
39 #include "libfshfs_thread_record.h"
40
41 #include "fshfs_catalog_file.h"
42
43 /* Retrieves the catalog B-tree key from a specific B-tree node record
44 * Returns 1 if successful or -1 on error
45 */
libfshfs_catalog_btree_file_get_key_from_node_by_index(libfshfs_btree_node_t * node,uint16_t record_index,libfshfs_catalog_btree_key_t ** node_key,libcerror_error_t ** error)46 int libfshfs_catalog_btree_file_get_key_from_node_by_index(
47 libfshfs_btree_node_t *node,
48 uint16_t record_index,
49 libfshfs_catalog_btree_key_t **node_key,
50 libcerror_error_t **error )
51 {
52 libfshfs_btree_node_record_t *node_record = NULL;
53 libfshfs_catalog_btree_key_t *safe_node_key = NULL;
54 static char *function = "libfshfs_catalog_btree_file_get_key_from_node_by_index";
55
56 if( node_key == NULL )
57 {
58 libcerror_error_set(
59 error,
60 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62 "%s: invalid catalog B-tree key.",
63 function );
64
65 return( -1 );
66 }
67 if( libfshfs_btree_node_get_record_by_index(
68 node,
69 record_index,
70 &node_record,
71 error ) == -1 )
72 {
73 libcerror_error_set(
74 error,
75 LIBCERROR_ERROR_DOMAIN_RUNTIME,
76 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
77 "%s: unable to retrieve node record: %" PRIu16 ".",
78 function,
79 record_index );
80
81 goto on_error;
82 }
83 if( node_record == NULL )
84 {
85 libcerror_error_set(
86 error,
87 LIBCERROR_ERROR_DOMAIN_RUNTIME,
88 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
89 "%s: missing B-tree node record: %" PRIu16 ".",
90 function,
91 record_index );
92
93 goto on_error;
94 }
95 if( node_record->key_value == NULL )
96 {
97 if( libfshfs_catalog_btree_key_initialize(
98 &safe_node_key,
99 error ) != 1 )
100 {
101 libcerror_error_set(
102 error,
103 LIBCERROR_ERROR_DOMAIN_RUNTIME,
104 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
105 "%s: unable to create catalog B-tree key.",
106 function );
107
108 goto on_error;
109 }
110 if( libfshfs_catalog_btree_key_read_data(
111 safe_node_key,
112 node_record->data,
113 node_record->data_size,
114 error ) != 1 )
115 {
116 libcerror_error_set(
117 error,
118 LIBCERROR_ERROR_DOMAIN_IO,
119 LIBCERROR_IO_ERROR_READ_FAILED,
120 "%s: unable to read catalog B-tree key.",
121 function );
122
123 goto on_error;
124 }
125 node_record->key_value = (intptr_t *) safe_node_key;
126 node_record->key_value_free_function = (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_catalog_btree_key_free;
127 }
128 *node_key = (libfshfs_catalog_btree_key_t *) node_record->key_value;
129
130 return( 1 );
131
132 on_error:
133 if( safe_node_key != NULL )
134 {
135 libfshfs_catalog_btree_key_free(
136 &safe_node_key,
137 NULL );
138 }
139 return( -1 );
140 }
141
142 /* Retrieves a sub node number for from the catalog B-tree key
143 * Returns 1 if successful or -1 on error
144 */
libfshfs_catalog_btree_file_get_sub_node_number_from_key(libfshfs_catalog_btree_key_t * node_key,uint32_t * sub_node_number,libcerror_error_t ** error)145 int libfshfs_catalog_btree_file_get_sub_node_number_from_key(
146 libfshfs_catalog_btree_key_t *node_key,
147 uint32_t *sub_node_number,
148 libcerror_error_t **error )
149 {
150 static char *function = "libfshfs_catalog_btree_file_get_sub_node_number_from_key";
151
152 if( node_key == NULL )
153 {
154 libcerror_error_set(
155 error,
156 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
157 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
158 "%s: invalid catalog B-tree key.",
159 function );
160
161 return( -1 );
162 }
163 if( node_key->record_data == NULL )
164 {
165 libcerror_error_set(
166 error,
167 LIBCERROR_ERROR_DOMAIN_RUNTIME,
168 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
169 "%s: invalid catalog B-tree key - missing record data.",
170 function );
171
172 return( -1 );
173 }
174 if( node_key->record_data_size < 4 )
175 {
176 libcerror_error_set(
177 error,
178 LIBCERROR_ERROR_DOMAIN_RUNTIME,
179 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
180 "%s: invalid catalog B-tree key - record data size value out of bounds.",
181 function );
182
183 return( -1 );
184 }
185 if( sub_node_number == NULL )
186 {
187 libcerror_error_set(
188 error,
189 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
190 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
191 "%s: invalid sub node number.",
192 function );
193
194 return( -1 );
195 }
196 byte_stream_copy_to_uint32_big_endian(
197 node_key->record_data,
198 *sub_node_number );
199
200 return( 1 );
201 }
202
203 /* Retrieves a thread record for from the catalog B-tree key
204 * Returns 1 if successful, 0 if not found or -1 on error
205 */
libfshfs_catalog_btree_file_get_thread_record_from_key(libfshfs_catalog_btree_key_t * node_key,libfshfs_thread_record_t ** thread_record,libcerror_error_t ** error)206 int libfshfs_catalog_btree_file_get_thread_record_from_key(
207 libfshfs_catalog_btree_key_t *node_key,
208 libfshfs_thread_record_t **thread_record,
209 libcerror_error_t **error )
210 {
211 libfshfs_thread_record_t *safe_thread_record = NULL;
212 static char *function = "libfshfs_catalog_btree_file_get_thread_record_from_key";
213 uint16_t record_type = 0;
214 int result = 0;
215
216 if( node_key == NULL )
217 {
218 libcerror_error_set(
219 error,
220 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
221 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
222 "%s: invalid catalog B-tree key.",
223 function );
224
225 return( -1 );
226 }
227 if( node_key->record_data == NULL )
228 {
229 libcerror_error_set(
230 error,
231 LIBCERROR_ERROR_DOMAIN_RUNTIME,
232 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
233 "%s: invalid catalog B-tree key - missing record data.",
234 function );
235
236 return( -1 );
237 }
238 if( node_key->record_data_size < 2 )
239 {
240 libcerror_error_set(
241 error,
242 LIBCERROR_ERROR_DOMAIN_RUNTIME,
243 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
244 "%s: invalid catalog B-tree key - record data size value out of bounds.",
245 function );
246
247 goto on_error;
248 }
249 if( thread_record == NULL )
250 {
251 libcerror_error_set(
252 error,
253 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
254 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
255 "%s: invalid thread record.",
256 function );
257
258 return( -1 );
259 }
260 if( *thread_record != NULL )
261 {
262 libcerror_error_set(
263 error,
264 LIBCERROR_ERROR_DOMAIN_RUNTIME,
265 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
266 "%s: invalid thread record value already set.",
267 function );
268
269 return( -1 );
270 }
271 byte_stream_copy_to_uint16_big_endian(
272 node_key->record_data,
273 record_type );
274
275 switch( record_type )
276 {
277 case LIBFSHFS_RECORD_TYPE_HFSPLUS_DIRECTORY_THREAD_RECORD:
278 case LIBFSHFS_RECORD_TYPE_HFSPLUS_FILE_THREAD_RECORD:
279 case LIBFSHFS_RECORD_TYPE_HFS_DIRECTORY_THREAD_RECORD:
280 case LIBFSHFS_RECORD_TYPE_HFS_FILE_THREAD_RECORD:
281 if( libfshfs_thread_record_initialize(
282 &safe_thread_record,
283 node_key->parent_identifier,
284 error ) != 1 )
285 {
286 libcerror_error_set(
287 error,
288 LIBCERROR_ERROR_DOMAIN_RUNTIME,
289 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
290 "%s: unable to create thread record.",
291 function );
292
293 goto on_error;
294 }
295 if( libfshfs_thread_record_read_data(
296 safe_thread_record,
297 node_key->record_data,
298 node_key->record_data_size,
299 error ) != 1 )
300 {
301 libcerror_error_set(
302 error,
303 LIBCERROR_ERROR_DOMAIN_IO,
304 LIBCERROR_IO_ERROR_READ_FAILED,
305 "%s: unable to read thread record.",
306 function );
307
308 goto on_error;
309 }
310 *thread_record = safe_thread_record;
311
312 result = 1;
313
314 break;
315
316 default:
317 break;
318 }
319 return( result );
320
321 on_error:
322 if( safe_thread_record != NULL )
323 {
324 libfshfs_thread_record_free(
325 &safe_thread_record,
326 NULL );
327 }
328 return( -1 );
329 }
330
331 /* Retrieves a thread record for a specific identifier from the catalog B-tree leaf node
332 * Returns 1 if successful, 0 if not found or -1 on error
333 */
libfshfs_catalog_btree_file_get_thread_record_from_leaf_node(libfshfs_btree_file_t * btree_file,libfshfs_btree_node_t * node,uint32_t identifier,libfshfs_thread_record_t ** thread_record,libcerror_error_t ** error)334 int libfshfs_catalog_btree_file_get_thread_record_from_leaf_node(
335 libfshfs_btree_file_t *btree_file,
336 libfshfs_btree_node_t *node,
337 uint32_t identifier,
338 libfshfs_thread_record_t **thread_record,
339 libcerror_error_t **error )
340 {
341 libfshfs_catalog_btree_key_t *node_key = NULL;
342 static char *function = "libfshfs_catalog_btree_file_get_thread_record_from_leaf_node";
343 uint16_t record_index = 0;
344 int is_leaf_node = 0;
345 int result = 0;
346
347 if( btree_file == NULL )
348 {
349 libcerror_error_set(
350 error,
351 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
352 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
353 "%s: invalid B-tree file.",
354 function );
355
356 return( -1 );
357 }
358 if( node == NULL )
359 {
360 libcerror_error_set(
361 error,
362 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
363 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
364 "%s: invalid B-tree node.",
365 function );
366
367 return( -1 );
368 }
369 if( node->descriptor == NULL )
370 {
371 libcerror_error_set(
372 error,
373 LIBCERROR_ERROR_DOMAIN_RUNTIME,
374 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
375 "%s: invalid B-tree node - missing descriptor.",
376 function );
377
378 return( -1 );
379 }
380 if( thread_record == NULL )
381 {
382 libcerror_error_set(
383 error,
384 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
385 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
386 "%s: invalid thread record.",
387 function );
388
389 return( -1 );
390 }
391 is_leaf_node = libfshfs_btree_node_is_leaf_node(
392 node,
393 error );
394
395 if( is_leaf_node == -1 )
396 {
397 libcerror_error_set(
398 error,
399 LIBCERROR_ERROR_DOMAIN_RUNTIME,
400 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
401 "%s: unable to determine if B-tree node is a leaf node.",
402 function );
403
404 goto on_error;
405 }
406 else if( is_leaf_node == 0 )
407 {
408 libcerror_error_set(
409 error,
410 LIBCERROR_ERROR_DOMAIN_RUNTIME,
411 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
412 "%s: invalid node - not a leaf node.",
413 function );
414
415 goto on_error;
416 }
417 for( record_index = 0;
418 record_index < node->descriptor->number_of_records;
419 record_index++ )
420 {
421 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
422 node,
423 record_index,
424 &node_key,
425 error ) == -1 )
426 {
427 libcerror_error_set(
428 error,
429 LIBCERROR_ERROR_DOMAIN_RUNTIME,
430 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
431 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
432 function,
433 record_index );
434
435 goto on_error;
436 }
437 if( node_key == NULL )
438 {
439 libcerror_error_set(
440 error,
441 LIBCERROR_ERROR_DOMAIN_RUNTIME,
442 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
443 "%s: missing catalog B-tree key: %" PRIu16 ".",
444 function,
445 record_index );
446
447 goto on_error;
448 }
449 if( ( node_key->parent_identifier == identifier )
450 && ( node_key->name_size == 0 ) )
451 {
452 result = libfshfs_catalog_btree_file_get_thread_record_from_key(
453 node_key,
454 thread_record,
455 error );
456
457 if( result == -1 )
458 {
459 libcerror_error_set(
460 error,
461 LIBCERROR_ERROR_DOMAIN_RUNTIME,
462 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
463 "%s: unable to retrieve thread record from catalog B-Tree key.",
464 function );
465
466 goto on_error;
467 }
468 }
469 if( ( result == 1 )
470 || ( node_key->parent_identifier > identifier ) )
471 {
472 break;
473 }
474 }
475 return( result );
476
477 on_error:
478 if( *thread_record != NULL )
479 {
480 libfshfs_thread_record_free(
481 thread_record,
482 NULL );
483 }
484 return( -1 );
485 }
486
487 /* Retrieves a thread record for a specific identifier from the catalog B-tree branch node
488 * Returns 1 if successful, 0 if not found or -1 on error
489 */
libfshfs_catalog_btree_file_get_thread_record_from_branch_node(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,libfshfs_btree_node_t * node,uint32_t identifier,libfshfs_thread_record_t ** thread_record,int recursion_depth,libcerror_error_t ** error)490 int libfshfs_catalog_btree_file_get_thread_record_from_branch_node(
491 libfshfs_btree_file_t *btree_file,
492 libbfio_handle_t *file_io_handle,
493 libfshfs_btree_node_t *node,
494 uint32_t identifier,
495 libfshfs_thread_record_t **thread_record,
496 int recursion_depth,
497 libcerror_error_t **error )
498 {
499 libfshfs_btree_node_t *sub_node = NULL;
500 libfshfs_catalog_btree_key_t *last_node_key = NULL;
501 libfshfs_catalog_btree_key_t *node_key = NULL;
502 static char *function = "libfshfs_catalog_btree_file_get_thread_record_from_branch_node";
503 uint32_t sub_node_number = 0;
504 uint16_t record_index = 0;
505 uint8_t node_type = 0;
506 int is_branch_node = 0;
507 int result = 0;
508
509 if( btree_file == NULL )
510 {
511 libcerror_error_set(
512 error,
513 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
514 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
515 "%s: invalid B-tree file.",
516 function );
517
518 return( -1 );
519 }
520 if( node == NULL )
521 {
522 libcerror_error_set(
523 error,
524 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
525 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
526 "%s: invalid B-tree node.",
527 function );
528
529 return( -1 );
530 }
531 if( node->descriptor == NULL )
532 {
533 libcerror_error_set(
534 error,
535 LIBCERROR_ERROR_DOMAIN_RUNTIME,
536 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
537 "%s: invalid B-tree node - missing descriptor.",
538 function );
539
540 return( -1 );
541 }
542 if( thread_record == NULL )
543 {
544 libcerror_error_set(
545 error,
546 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
547 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
548 "%s: invalid thread record.",
549 function );
550
551 return( -1 );
552 }
553 if( ( recursion_depth < 0 )
554 || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
555 {
556 libcerror_error_set(
557 error,
558 LIBCERROR_ERROR_DOMAIN_RUNTIME,
559 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
560 "%s: invalid recursion depth value out of bounds.",
561 function );
562
563 return( -1 );
564 }
565 is_branch_node = libfshfs_btree_node_is_branch_node(
566 node,
567 error );
568
569 if( is_branch_node == -1 )
570 {
571 libcerror_error_set(
572 error,
573 LIBCERROR_ERROR_DOMAIN_RUNTIME,
574 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
575 "%s: unable to determine if B-tree node is a branch node.",
576 function );
577
578 goto on_error;
579 }
580 else if( is_branch_node == 0 )
581 {
582 libcerror_error_set(
583 error,
584 LIBCERROR_ERROR_DOMAIN_RUNTIME,
585 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
586 "%s: invalid node - not a branch node.",
587 function );
588
589 goto on_error;
590 }
591 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
592 node,
593 0,
594 &last_node_key,
595 error ) == -1 )
596 {
597 libcerror_error_set(
598 error,
599 LIBCERROR_ERROR_DOMAIN_RUNTIME,
600 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
601 "%s: unable to retrieve catalog B-tree key: 0.",
602 function );
603
604 goto on_error;
605 }
606 node_key = last_node_key;
607
608 for( record_index = 1;
609 record_index <= node->descriptor->number_of_records;
610 record_index++ )
611 {
612 if( record_index < node->descriptor->number_of_records )
613 {
614 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
615 node,
616 record_index,
617 &node_key,
618 error ) == -1 )
619 {
620 libcerror_error_set(
621 error,
622 LIBCERROR_ERROR_DOMAIN_RUNTIME,
623 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
624 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
625 function,
626 record_index );
627
628 goto on_error;
629 }
630 }
631 if( node_key == NULL )
632 {
633 libcerror_error_set(
634 error,
635 LIBCERROR_ERROR_DOMAIN_RUNTIME,
636 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
637 "%s: missing catalog B-tree key: %" PRIu16 ".",
638 function,
639 record_index );
640
641 goto on_error;
642 }
643 if( ( record_index == node->descriptor->number_of_records )
644 || ( node_key->parent_identifier >= identifier ) )
645 {
646 if( libfshfs_catalog_btree_file_get_sub_node_number_from_key(
647 last_node_key,
648 &sub_node_number,
649 error ) != 1 )
650 {
651 libcerror_error_set(
652 error,
653 LIBCERROR_ERROR_DOMAIN_RUNTIME,
654 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
655 "%s: unable to retrieve sub node number from catalog B-Tree key.",
656 function );
657
658 goto on_error;
659 }
660 #if defined( HAVE_DEBUG_OUTPUT )
661 if( libcnotify_verbose != 0 )
662 {
663 libcnotify_printf(
664 "%s: B-tree sub node number\t: %" PRIu32 "\n",
665 function,
666 sub_node_number );
667
668 libcnotify_printf(
669 "\n" );
670 }
671 #endif
672 if( libfshfs_btree_file_get_node_by_number(
673 btree_file,
674 file_io_handle,
675 sub_node_number,
676 &sub_node,
677 recursion_depth,
678 error ) == -1 )
679 {
680 libcerror_error_set(
681 error,
682 LIBCERROR_ERROR_DOMAIN_RUNTIME,
683 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
684 "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
685 function,
686 sub_node_number );
687
688 goto on_error;
689 }
690 if( libfshfs_btree_node_get_node_type(
691 sub_node,
692 &node_type,
693 error ) != 1 )
694 {
695 libcerror_error_set(
696 error,
697 LIBCERROR_ERROR_DOMAIN_RUNTIME,
698 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
699 "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
700 function,
701 sub_node_number );
702
703 goto on_error;
704 }
705 if( node_type == 0x00 )
706 {
707 result = libfshfs_catalog_btree_file_get_thread_record_from_branch_node(
708 btree_file,
709 file_io_handle,
710 sub_node,
711 identifier,
712 thread_record,
713 recursion_depth + 1,
714 error );
715 }
716 else if( node_type == 0xff )
717 {
718 result = libfshfs_catalog_btree_file_get_thread_record_from_leaf_node(
719 btree_file,
720 sub_node,
721 identifier,
722 thread_record,
723 error );
724 }
725 if( result == -1 )
726 {
727 libcerror_error_set(
728 error,
729 LIBCERROR_ERROR_DOMAIN_RUNTIME,
730 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
731 "%s: unable to retrieve thread record from catalog B-tree node: %" PRIu32 ".",
732 function,
733 sub_node_number );
734
735 goto on_error;
736 }
737 if( ( result == 1 )
738 || ( node_key->parent_identifier > identifier ) )
739 {
740 break;
741 }
742 }
743 last_node_key = node_key;
744 }
745 return( result );
746
747 on_error:
748 if( *thread_record != NULL )
749 {
750 libfshfs_thread_record_free(
751 thread_record,
752 NULL );
753 }
754 return( -1 );
755 }
756
757 /* Retrieves a thread record for a specific identifier from the catalog B-tree file
758 * Returns 1 if successful, 0 if not found or -1 on error
759 */
libfshfs_catalog_btree_file_get_thread_record(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,uint32_t identifier,libfshfs_thread_record_t ** thread_record,libcerror_error_t ** error)760 int libfshfs_catalog_btree_file_get_thread_record(
761 libfshfs_btree_file_t *btree_file,
762 libbfio_handle_t *file_io_handle,
763 uint32_t identifier,
764 libfshfs_thread_record_t **thread_record,
765 libcerror_error_t **error )
766 {
767 libfshfs_btree_node_t *root_node = NULL;
768 static char *function = "libfshfs_catalog_btree_file_get_thread_record";
769 uint8_t node_type = 0;
770 int result = 0;
771
772 if( libfshfs_btree_file_get_root_node(
773 btree_file,
774 file_io_handle,
775 &root_node,
776 0,
777 error ) == -1 )
778 {
779 libcerror_error_set(
780 error,
781 LIBCERROR_ERROR_DOMAIN_RUNTIME,
782 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
783 "%s: unable to retrieve B-tree root node.",
784 function );
785
786 return( -1 );
787 }
788 if( libfshfs_btree_node_get_node_type(
789 root_node,
790 &node_type,
791 error ) != 1 )
792 {
793 libcerror_error_set(
794 error,
795 LIBCERROR_ERROR_DOMAIN_RUNTIME,
796 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
797 "%s: unable to determine if B-tree root node is a branch node.",
798 function );
799
800 return( -1 );
801 }
802 if( node_type == 0x00 )
803 {
804 result = libfshfs_catalog_btree_file_get_thread_record_from_branch_node(
805 btree_file,
806 file_io_handle,
807 root_node,
808 identifier,
809 thread_record,
810 1,
811 error );
812 }
813 else if( node_type == 0xff )
814 {
815 result = libfshfs_catalog_btree_file_get_thread_record_from_leaf_node(
816 btree_file,
817 root_node,
818 identifier,
819 thread_record,
820 error );
821 }
822 if( result == -1 )
823 {
824 libcerror_error_set(
825 error,
826 LIBCERROR_ERROR_DOMAIN_RUNTIME,
827 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
828 "%s: unable to retrieve thread record: %" PRIu32 " from catalog B-tree root node.",
829 function,
830 identifier );
831
832 return( -1 );
833 }
834 return( result );
835 }
836
837 /* Retrieves a directory entry for from the catalog B-tree key
838 * Returns 1 if successful, 0 if not found or -1 on error
839 */
libfshfs_catalog_btree_file_get_directory_entry_from_key(libfshfs_catalog_btree_key_t * node_key,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)840 int libfshfs_catalog_btree_file_get_directory_entry_from_key(
841 libfshfs_catalog_btree_key_t *node_key,
842 libfshfs_directory_entry_t **directory_entry,
843 libcerror_error_t **error )
844 {
845 libfshfs_directory_entry_t *safe_directory_entry = NULL;
846 libfshfs_directory_record_t *directory_record = NULL;
847 libfshfs_file_record_t *file_record = NULL;
848 intptr_t *catalog_record = NULL;
849 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_key";
850 uint16_t record_type = 0;
851 int result = 0;
852
853 if( node_key == NULL )
854 {
855 libcerror_error_set(
856 error,
857 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
858 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
859 "%s: invalid catalog B-tree key.",
860 function );
861
862 return( -1 );
863 }
864 if( node_key->record_data == NULL )
865 {
866 libcerror_error_set(
867 error,
868 LIBCERROR_ERROR_DOMAIN_RUNTIME,
869 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
870 "%s: invalid catalog B-tree key - missing record data.",
871 function );
872
873 return( -1 );
874 }
875 if( node_key->record_data_size < 2 )
876 {
877 libcerror_error_set(
878 error,
879 LIBCERROR_ERROR_DOMAIN_RUNTIME,
880 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
881 "%s: invalid catalog B-tree key - record data size value out of bounds.",
882 function );
883
884 goto on_error;
885 }
886 if( directory_entry == NULL )
887 {
888 libcerror_error_set(
889 error,
890 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
891 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
892 "%s: invalid directory entry.",
893 function );
894
895 return( -1 );
896 }
897 if( *directory_entry != NULL )
898 {
899 libcerror_error_set(
900 error,
901 LIBCERROR_ERROR_DOMAIN_RUNTIME,
902 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
903 "%s: invalid directory entry value already set.",
904 function );
905
906 return( -1 );
907 }
908 byte_stream_copy_to_uint16_big_endian(
909 node_key->record_data,
910 record_type );
911
912 switch( record_type )
913 {
914 case LIBFSHFS_RECORD_TYPE_HFSPLUS_DIRECTORY_RECORD:
915 case LIBFSHFS_RECORD_TYPE_HFS_DIRECTORY_RECORD:
916 if( libfshfs_directory_record_initialize(
917 &directory_record,
918 error ) != 1 )
919 {
920 libcerror_error_set(
921 error,
922 LIBCERROR_ERROR_DOMAIN_RUNTIME,
923 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
924 "%s: unable to create directory record.",
925 function );
926
927 goto on_error;
928 }
929 if( libfshfs_directory_record_read_data(
930 directory_record,
931 node_key->record_data,
932 node_key->record_data_size,
933 error ) != 1 )
934 {
935 libcerror_error_set(
936 error,
937 LIBCERROR_ERROR_DOMAIN_IO,
938 LIBCERROR_IO_ERROR_READ_FAILED,
939 "%s: unable to read directory record.",
940 function );
941
942 goto on_error;
943 }
944 catalog_record = (intptr_t *) directory_record;
945
946 break;
947
948 case LIBFSHFS_RECORD_TYPE_HFSPLUS_FILE_RECORD:
949 case LIBFSHFS_RECORD_TYPE_HFS_FILE_RECORD:
950 if( libfshfs_file_record_initialize(
951 &file_record,
952 error ) != 1 )
953 {
954 libcerror_error_set(
955 error,
956 LIBCERROR_ERROR_DOMAIN_RUNTIME,
957 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
958 "%s: unable to create file record.",
959 function );
960
961 goto on_error;
962 }
963 if( libfshfs_file_record_read_data(
964 file_record,
965 node_key->record_data,
966 node_key->record_data_size,
967 error ) != 1 )
968 {
969 libcerror_error_set(
970 error,
971 LIBCERROR_ERROR_DOMAIN_IO,
972 LIBCERROR_IO_ERROR_READ_FAILED,
973 "%s: unable to read file record.",
974 function );
975
976 goto on_error;
977 }
978 catalog_record = (intptr_t *) file_record;
979
980 break;
981
982 default:
983 break;
984 }
985 if( catalog_record != NULL )
986 {
987 if( libfshfs_directory_entry_initialize(
988 &safe_directory_entry,
989 error ) != 1 )
990 {
991 libcerror_error_set(
992 error,
993 LIBCERROR_ERROR_DOMAIN_RUNTIME,
994 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
995 "%s: unable to create directory entry.",
996 function );
997
998 goto on_error;
999 }
1000 if( libfshfs_directory_entry_set_name(
1001 safe_directory_entry,
1002 node_key->name_data,
1003 node_key->name_size,
1004 error ) != 1 )
1005 {
1006 libcerror_error_set(
1007 error,
1008 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1009 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1010 "%s: unable to set name of directory entry.",
1011 function );
1012
1013 goto on_error;
1014 }
1015 safe_directory_entry->parent_identifier = node_key->parent_identifier;
1016
1017 if( libfshfs_directory_entry_set_catalog_record(
1018 safe_directory_entry,
1019 record_type,
1020 catalog_record,
1021 error ) != 1 )
1022 {
1023 libcerror_error_set(
1024 error,
1025 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1027 "%s: unable to set catalog record of directory entry.",
1028 function );
1029
1030 goto on_error;
1031 }
1032 directory_record = NULL;
1033 file_record = NULL;
1034
1035 *directory_entry = safe_directory_entry;
1036
1037 result = 1;
1038 }
1039 return( result );
1040
1041 on_error:
1042 if( file_record != NULL )
1043 {
1044 libfshfs_file_record_free(
1045 &file_record,
1046 NULL );
1047 }
1048 if( directory_record != NULL )
1049 {
1050 libfshfs_directory_record_free(
1051 &directory_record,
1052 NULL );
1053 }
1054 if( safe_directory_entry != NULL )
1055 {
1056 libfshfs_directory_entry_free(
1057 &safe_directory_entry,
1058 NULL );
1059 }
1060 return( -1 );
1061 }
1062
1063 /* Retrieves a directory entry for a specific thread record from the catalog B-tree leaf node
1064 * Returns 1 if successful, 0 if not found or -1 on error
1065 */
libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_thread_record(libfshfs_btree_file_t * btree_file,libfshfs_btree_node_t * node,libfshfs_thread_record_t * thread_record,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)1066 int libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_thread_record(
1067 libfshfs_btree_file_t *btree_file,
1068 libfshfs_btree_node_t *node,
1069 libfshfs_thread_record_t *thread_record,
1070 libfshfs_directory_entry_t **directory_entry,
1071 libcerror_error_t **error )
1072 {
1073 libfshfs_catalog_btree_key_t *node_key = NULL;
1074 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_thread_record";
1075 uint16_t record_index = 0;
1076 uint16_t record_type = 0;
1077 int compare_result = 0;
1078 int is_leaf_node = 0;
1079 int result = 0;
1080
1081 if( btree_file == NULL )
1082 {
1083 libcerror_error_set(
1084 error,
1085 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1086 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1087 "%s: invalid B-tree file.",
1088 function );
1089
1090 return( -1 );
1091 }
1092 if( node == NULL )
1093 {
1094 libcerror_error_set(
1095 error,
1096 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1097 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1098 "%s: invalid B-tree node.",
1099 function );
1100
1101 return( -1 );
1102 }
1103 if( node->descriptor == NULL )
1104 {
1105 libcerror_error_set(
1106 error,
1107 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1108 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1109 "%s: invalid B-tree node - missing descriptor.",
1110 function );
1111
1112 return( -1 );
1113 }
1114 if( thread_record == NULL )
1115 {
1116 libcerror_error_set(
1117 error,
1118 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1119 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1120 "%s: invalid thread record.",
1121 function );
1122
1123 return( -1 );
1124 }
1125 if( directory_entry == NULL )
1126 {
1127 libcerror_error_set(
1128 error,
1129 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1130 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1131 "%s: invalid directory entry.",
1132 function );
1133
1134 return( -1 );
1135 }
1136 is_leaf_node = libfshfs_btree_node_is_leaf_node(
1137 node,
1138 error );
1139
1140 if( is_leaf_node == -1 )
1141 {
1142 libcerror_error_set(
1143 error,
1144 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1145 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1146 "%s: unable to determine if B-tree node is a leaf node.",
1147 function );
1148
1149 goto on_error;
1150 }
1151 else if( is_leaf_node == 0 )
1152 {
1153 libcerror_error_set(
1154 error,
1155 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1156 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1157 "%s: invalid node - not a leaf node.",
1158 function );
1159
1160 goto on_error;
1161 }
1162 for( record_index = 0;
1163 record_index < node->descriptor->number_of_records;
1164 record_index++ )
1165 {
1166 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
1167 node,
1168 record_index,
1169 &node_key,
1170 error ) == -1 )
1171 {
1172 libcerror_error_set(
1173 error,
1174 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1175 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1176 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
1177 function,
1178 record_index );
1179
1180 goto on_error;
1181 }
1182 if( node_key == NULL )
1183 {
1184 libcerror_error_set(
1185 error,
1186 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1187 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1188 "%s: missing catalog B-tree key: %" PRIu16 ".",
1189 function,
1190 record_index );
1191
1192 goto on_error;
1193 }
1194 if( node_key->parent_identifier == thread_record->parent_identifier )
1195 {
1196 if( node_key->record_data_size < 2 )
1197 {
1198 libcerror_error_set(
1199 error,
1200 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1201 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1202 "%s: invalid catalog B-tree key: %" PRIu16 " - record data size value out of bounds.",
1203 function,
1204 record_index );
1205
1206 goto on_error;
1207 }
1208 byte_stream_copy_to_uint16_big_endian(
1209 node_key->record_data,
1210 record_type );
1211
1212 switch( record_type )
1213 {
1214 case LIBFSHFS_RECORD_TYPE_HFSPLUS_DIRECTORY_RECORD:
1215 case LIBFSHFS_RECORD_TYPE_HFSPLUS_FILE_RECORD:
1216 case LIBFSHFS_RECORD_TYPE_HFS_DIRECTORY_RECORD:
1217 case LIBFSHFS_RECORD_TYPE_HFS_FILE_RECORD:
1218 compare_result = libfshfs_catalog_btree_key_compare_name(
1219 node_key,
1220 thread_record->name,
1221 thread_record->name_size,
1222 error );
1223
1224 if( compare_result == -1 )
1225 {
1226 libcerror_error_set(
1227 error,
1228 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1229 LIBCERROR_RUNTIME_ERROR_GENERIC,
1230 "%s: unable to compare thread record name with catalog B-tree key name.",
1231 function );
1232
1233 goto on_error;
1234 }
1235 break;
1236
1237 default:
1238 compare_result = LIBUNA_COMPARE_LESS;
1239 break;
1240 }
1241 if( compare_result != 0 )
1242 {
1243 result = libfshfs_catalog_btree_file_get_directory_entry_from_key(
1244 node_key,
1245 directory_entry,
1246 error );
1247
1248 if( result == -1 )
1249 {
1250 libcerror_error_set(
1251 error,
1252 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1253 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1254 "%s: unable to retrieve directory entry from record data.",
1255 function );
1256
1257 goto on_error;
1258 }
1259 }
1260 }
1261 if( ( result == 1 )
1262 || ( node_key->parent_identifier > thread_record->parent_identifier ) )
1263 {
1264 break;
1265 }
1266 }
1267 return( result );
1268
1269 on_error:
1270 if( *directory_entry != NULL )
1271 {
1272 libfshfs_directory_entry_free(
1273 directory_entry,
1274 NULL );
1275 }
1276 return( -1 );
1277 }
1278
1279 /* Retrieves a directory entry for a specific thread record from the catalog B-tree branch node
1280 * Returns 1 if successful, 0 if not found or -1 on error
1281 */
libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_thread_record(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,libfshfs_btree_node_t * node,libfshfs_thread_record_t * thread_record,libfshfs_directory_entry_t ** directory_entry,int recursion_depth,libcerror_error_t ** error)1282 int libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_thread_record(
1283 libfshfs_btree_file_t *btree_file,
1284 libbfio_handle_t *file_io_handle,
1285 libfshfs_btree_node_t *node,
1286 libfshfs_thread_record_t *thread_record,
1287 libfshfs_directory_entry_t **directory_entry,
1288 int recursion_depth,
1289 libcerror_error_t **error )
1290 {
1291 libfshfs_btree_node_t *sub_node = NULL;
1292 libfshfs_catalog_btree_key_t *last_node_key = NULL;
1293 libfshfs_catalog_btree_key_t *node_key = NULL;
1294 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_thread_record";
1295 uint32_t sub_node_number = 0;
1296 uint16_t record_index = 0;
1297 uint8_t node_type = 0;
1298 int is_branch_node = 0;
1299 int result = 0;
1300
1301 if( btree_file == NULL )
1302 {
1303 libcerror_error_set(
1304 error,
1305 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1306 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1307 "%s: invalid B-tree file.",
1308 function );
1309
1310 return( -1 );
1311 }
1312 if( node == NULL )
1313 {
1314 libcerror_error_set(
1315 error,
1316 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1317 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1318 "%s: invalid B-tree node.",
1319 function );
1320
1321 return( -1 );
1322 }
1323 if( node->descriptor == NULL )
1324 {
1325 libcerror_error_set(
1326 error,
1327 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1328 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1329 "%s: invalid B-tree node - missing descriptor.",
1330 function );
1331
1332 return( -1 );
1333 }
1334 if( thread_record == NULL )
1335 {
1336 libcerror_error_set(
1337 error,
1338 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1339 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1340 "%s: invalid thread record.",
1341 function );
1342
1343 return( -1 );
1344 }
1345 if( directory_entry == NULL )
1346 {
1347 libcerror_error_set(
1348 error,
1349 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1350 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1351 "%s: invalid directory entry.",
1352 function );
1353
1354 return( -1 );
1355 }
1356 if( ( recursion_depth < 0 )
1357 || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1358 {
1359 libcerror_error_set(
1360 error,
1361 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1362 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1363 "%s: invalid recursion depth value out of bounds.",
1364 function );
1365
1366 return( -1 );
1367 }
1368 is_branch_node = libfshfs_btree_node_is_branch_node(
1369 node,
1370 error );
1371
1372 if( is_branch_node == -1 )
1373 {
1374 libcerror_error_set(
1375 error,
1376 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1377 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1378 "%s: unable to determine if B-tree node is a branch node.",
1379 function );
1380
1381 goto on_error;
1382 }
1383 else if( is_branch_node == 0 )
1384 {
1385 libcerror_error_set(
1386 error,
1387 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1388 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1389 "%s: invalid node - not a branch node.",
1390 function );
1391
1392 goto on_error;
1393 }
1394 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
1395 node,
1396 0,
1397 &last_node_key,
1398 error ) == -1 )
1399 {
1400 libcerror_error_set(
1401 error,
1402 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1403 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1404 "%s: unable to retrieve catalog B-tree key: 0.",
1405 function );
1406
1407 goto on_error;
1408 }
1409 node_key = last_node_key;
1410
1411 for( record_index = 1;
1412 record_index <= node->descriptor->number_of_records;
1413 record_index++ )
1414 {
1415 if( record_index < node->descriptor->number_of_records )
1416 {
1417 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
1418 node,
1419 record_index,
1420 &node_key,
1421 error ) == -1 )
1422 {
1423 libcerror_error_set(
1424 error,
1425 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1426 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1427 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
1428 function,
1429 record_index );
1430
1431 goto on_error;
1432 }
1433 }
1434 if( node_key == NULL )
1435 {
1436 libcerror_error_set(
1437 error,
1438 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1439 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1440 "%s: missing catalog B-tree key: %" PRIu16 ".",
1441 function,
1442 record_index );
1443
1444 goto on_error;
1445 }
1446 if( ( record_index == node->descriptor->number_of_records )
1447 || ( node_key->parent_identifier >= thread_record->parent_identifier ) )
1448 {
1449 if( libfshfs_catalog_btree_file_get_sub_node_number_from_key(
1450 last_node_key,
1451 &sub_node_number,
1452 error ) != 1 )
1453 {
1454 libcerror_error_set(
1455 error,
1456 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1457 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1458 "%s: unable to retrieve sub node number from catalog B-Tree key.",
1459 function );
1460
1461 goto on_error;
1462 }
1463 #if defined( HAVE_DEBUG_OUTPUT )
1464 if( libcnotify_verbose != 0 )
1465 {
1466 libcnotify_printf(
1467 "%s: B-tree sub node number\t: %" PRIu32 "\n",
1468 function,
1469 sub_node_number );
1470
1471 libcnotify_printf(
1472 "\n" );
1473 }
1474 #endif
1475 if( libfshfs_btree_file_get_node_by_number(
1476 btree_file,
1477 file_io_handle,
1478 sub_node_number,
1479 &sub_node,
1480 recursion_depth,
1481 error ) == -1 )
1482 {
1483 libcerror_error_set(
1484 error,
1485 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1486 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1487 "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
1488 function,
1489 sub_node_number );
1490
1491 goto on_error;
1492 }
1493 if( libfshfs_btree_node_get_node_type(
1494 sub_node,
1495 &node_type,
1496 error ) != 1 )
1497 {
1498 libcerror_error_set(
1499 error,
1500 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1501 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1502 "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
1503 function,
1504 sub_node_number );
1505
1506 goto on_error;
1507 }
1508 if( node_type == 0x00 )
1509 {
1510 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_thread_record(
1511 btree_file,
1512 file_io_handle,
1513 sub_node,
1514 thread_record,
1515 directory_entry,
1516 recursion_depth + 1,
1517 error );
1518 }
1519 else if( node_type == 0xff )
1520 {
1521 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_thread_record(
1522 btree_file,
1523 sub_node,
1524 thread_record,
1525 directory_entry,
1526 error );
1527 }
1528 if( result == -1 )
1529 {
1530 libcerror_error_set(
1531 error,
1532 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1533 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1534 "%s: unable to retrieve directory entry from catalog B-tree node: %" PRIu32 ".",
1535 function,
1536 sub_node_number );
1537
1538 goto on_error;
1539 }
1540 if( ( result == 1 )
1541 || ( node_key->parent_identifier > thread_record->parent_identifier ) )
1542 {
1543 break;
1544 }
1545 }
1546 last_node_key = node_key;
1547 }
1548 return( result );
1549
1550 on_error:
1551 if( *directory_entry != NULL )
1552 {
1553 libfshfs_directory_entry_free(
1554 directory_entry,
1555 NULL );
1556 }
1557 return( -1 );
1558 }
1559
1560 /* Retrieves a directory entry for a specific identifier from the catalog B-tree file
1561 * Returns 1 if successful, 0 if not found or -1 on error
1562 */
libfshfs_catalog_btree_file_get_directory_entry_by_identifier(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,uint32_t identifier,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)1563 int libfshfs_catalog_btree_file_get_directory_entry_by_identifier(
1564 libfshfs_btree_file_t *btree_file,
1565 libbfio_handle_t *file_io_handle,
1566 uint32_t identifier,
1567 libfshfs_directory_entry_t **directory_entry,
1568 libcerror_error_t **error )
1569 {
1570 libfshfs_btree_node_t *root_node = NULL;
1571 libfshfs_thread_record_t *thread_record = NULL;
1572 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_by_identifier";
1573 uint8_t node_type = 0;
1574 int result = 0;
1575
1576 result = libfshfs_catalog_btree_file_get_thread_record(
1577 btree_file,
1578 file_io_handle,
1579 identifier,
1580 &thread_record,
1581 error );
1582
1583 if( result == -1 )
1584 {
1585 libcerror_error_set(
1586 error,
1587 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1588 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1589 "%s: unable to retrieve thread record: %" PRIu32 " from catalog B-tree root node.",
1590 function,
1591 identifier );
1592
1593 goto on_error;
1594 }
1595 else if( result != 0 )
1596 {
1597 if( libfshfs_btree_file_get_root_node(
1598 btree_file,
1599 file_io_handle,
1600 &root_node,
1601 0,
1602 error ) == -1 )
1603 {
1604 libcerror_error_set(
1605 error,
1606 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1607 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1608 "%s: unable to retrieve B-tree root node.",
1609 function );
1610
1611 goto on_error;
1612 }
1613 if( libfshfs_btree_node_get_node_type(
1614 root_node,
1615 &node_type,
1616 error ) != 1 )
1617 {
1618 libcerror_error_set(
1619 error,
1620 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1621 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1622 "%s: unable to determine if B-tree root node type.",
1623 function );
1624
1625 goto on_error;
1626 }
1627 if( node_type == 0x00 )
1628 {
1629 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_thread_record(
1630 btree_file,
1631 file_io_handle,
1632 root_node,
1633 thread_record,
1634 directory_entry,
1635 1,
1636 error );
1637 }
1638 else if( node_type == 0xff )
1639 {
1640 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_thread_record(
1641 btree_file,
1642 root_node,
1643 thread_record,
1644 directory_entry,
1645 error );
1646 }
1647 if( result == -1 )
1648 {
1649 libcerror_error_set(
1650 error,
1651 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1652 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1653 "%s: unable to retrieve directory entry: %" PRIu32 " from catalog B-tree root node.",
1654 function,
1655 identifier );
1656
1657 goto on_error;
1658 }
1659 if( libfshfs_thread_record_free(
1660 &thread_record,
1661 error ) != 1 )
1662 {
1663 libcerror_error_set(
1664 error,
1665 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1666 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1667 "%s: unable to free thread record.",
1668 function );
1669
1670 goto on_error;
1671 }
1672 }
1673 return( result );
1674
1675 on_error:
1676 if( thread_record != NULL )
1677 {
1678 libfshfs_thread_record_free(
1679 &thread_record,
1680 NULL );
1681 }
1682 return( -1 );
1683 }
1684
1685 /* Retrieves a directory entry for an UTF-8 encoded name from the catalog B-tree leaf node
1686 * Returns 1 if successful, 0 if not found or -1 on error
1687 */
libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name(libfshfs_btree_file_t * btree_file,libfshfs_btree_node_t * node,uint32_t parent_identifier,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)1688 int libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name(
1689 libfshfs_btree_file_t *btree_file,
1690 libfshfs_btree_node_t *node,
1691 uint32_t parent_identifier,
1692 const uint8_t *utf8_string,
1693 size_t utf8_string_length,
1694 uint8_t use_case_folding,
1695 libfshfs_directory_entry_t **directory_entry,
1696 libcerror_error_t **error )
1697 {
1698 libfshfs_catalog_btree_key_t *node_key = NULL;
1699 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name";
1700 uint16_t record_index = 0;
1701 uint16_t record_type = 0;
1702 int compare_result = 0;
1703 int is_leaf_node = 0;
1704 int result = 0;
1705
1706 if( btree_file == NULL )
1707 {
1708 libcerror_error_set(
1709 error,
1710 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1711 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1712 "%s: invalid B-tree file.",
1713 function );
1714
1715 return( -1 );
1716 }
1717 if( node == NULL )
1718 {
1719 libcerror_error_set(
1720 error,
1721 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1722 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1723 "%s: invalid B-tree node.",
1724 function );
1725
1726 return( -1 );
1727 }
1728 if( node->descriptor == NULL )
1729 {
1730 libcerror_error_set(
1731 error,
1732 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1733 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1734 "%s: invalid B-tree node - missing descriptor.",
1735 function );
1736
1737 return( -1 );
1738 }
1739 if( directory_entry == NULL )
1740 {
1741 libcerror_error_set(
1742 error,
1743 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1744 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1745 "%s: invalid directory entry.",
1746 function );
1747
1748 return( -1 );
1749 }
1750 is_leaf_node = libfshfs_btree_node_is_leaf_node(
1751 node,
1752 error );
1753
1754 if( is_leaf_node == -1 )
1755 {
1756 libcerror_error_set(
1757 error,
1758 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1759 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1760 "%s: unable to determine if B-tree node is a leaf node.",
1761 function );
1762
1763 goto on_error;
1764 }
1765 else if( is_leaf_node == 0 )
1766 {
1767 libcerror_error_set(
1768 error,
1769 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1771 "%s: invalid node - not a leaf node.",
1772 function );
1773
1774 goto on_error;
1775 }
1776 for( record_index = 0;
1777 record_index < node->descriptor->number_of_records;
1778 record_index++ )
1779 {
1780 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
1781 node,
1782 record_index,
1783 &node_key,
1784 error ) == -1 )
1785 {
1786 libcerror_error_set(
1787 error,
1788 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1789 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1790 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
1791 function,
1792 record_index );
1793
1794 goto on_error;
1795 }
1796 if( node_key == NULL )
1797 {
1798 libcerror_error_set(
1799 error,
1800 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1801 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1802 "%s: missing catalog B-tree key: %" PRIu16 ".",
1803 function,
1804 record_index );
1805
1806 goto on_error;
1807 }
1808 if( node_key->parent_identifier == parent_identifier )
1809 {
1810 if( node_key->record_data_size < 2 )
1811 {
1812 libcerror_error_set(
1813 error,
1814 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1815 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1816 "%s: invalid catalog B-tree key: %" PRIu16 " - record data size value out of bounds.",
1817 function,
1818 record_index );
1819
1820 goto on_error;
1821 }
1822 byte_stream_copy_to_uint16_big_endian(
1823 node_key->record_data,
1824 record_type );
1825
1826 switch( record_type )
1827 {
1828 case LIBFSHFS_RECORD_TYPE_HFSPLUS_DIRECTORY_RECORD:
1829 case LIBFSHFS_RECORD_TYPE_HFSPLUS_FILE_RECORD:
1830 case LIBFSHFS_RECORD_TYPE_HFS_DIRECTORY_RECORD:
1831 case LIBFSHFS_RECORD_TYPE_HFS_FILE_RECORD:
1832 compare_result = libfshfs_catalog_btree_key_compare_name_with_utf8_string(
1833 node_key,
1834 utf8_string,
1835 utf8_string_length,
1836 use_case_folding,
1837 error );
1838
1839 if( compare_result == -1 )
1840 {
1841 libcerror_error_set(
1842 error,
1843 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1844 LIBCERROR_RUNTIME_ERROR_GENERIC,
1845 "%s: unable to compare UTF-8 string with catalog B-tree key name.",
1846 function );
1847
1848 goto on_error;
1849 }
1850 break;
1851
1852 default:
1853 compare_result = LIBUNA_COMPARE_LESS;
1854 break;
1855 }
1856 if( compare_result == LIBUNA_COMPARE_EQUAL )
1857 {
1858 result = libfshfs_catalog_btree_file_get_directory_entry_from_key(
1859 node_key,
1860 directory_entry,
1861 error );
1862
1863 if( result == -1 )
1864 {
1865 libcerror_error_set(
1866 error,
1867 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1868 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1869 "%s: unable to retrieve directory entry from record data.",
1870 function );
1871
1872 goto on_error;
1873 }
1874 }
1875 }
1876 if( ( result == 1 )
1877 || ( node_key->parent_identifier > parent_identifier ) )
1878 {
1879 break;
1880 }
1881 }
1882 return( result );
1883
1884 on_error:
1885 if( *directory_entry != NULL )
1886 {
1887 libfshfs_directory_entry_free(
1888 directory_entry,
1889 NULL );
1890 }
1891 return( -1 );
1892 }
1893
1894 /* Retrieves a directory entry for an UTF-8 encoded name from the catalog B-tree branch node
1895 * Returns 1 if successful, 0 if not found or -1 on error
1896 */
libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,libfshfs_btree_node_t * node,uint32_t parent_identifier,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,int recursion_depth,libcerror_error_t ** error)1897 int libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name(
1898 libfshfs_btree_file_t *btree_file,
1899 libbfio_handle_t *file_io_handle,
1900 libfshfs_btree_node_t *node,
1901 uint32_t parent_identifier,
1902 const uint8_t *utf8_string,
1903 size_t utf8_string_length,
1904 uint8_t use_case_folding,
1905 libfshfs_directory_entry_t **directory_entry,
1906 int recursion_depth,
1907 libcerror_error_t **error )
1908 {
1909 libfshfs_btree_node_t *sub_node = NULL;
1910 libfshfs_catalog_btree_key_t *last_node_key = NULL;
1911 libfshfs_catalog_btree_key_t *node_key = NULL;
1912 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name";
1913 uint32_t sub_node_number = 0;
1914 uint16_t record_index = 0;
1915 uint8_t node_type = 0;
1916 int is_branch_node = 0;
1917 int result = 0;
1918
1919 if( btree_file == NULL )
1920 {
1921 libcerror_error_set(
1922 error,
1923 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1924 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1925 "%s: invalid B-tree file.",
1926 function );
1927
1928 return( -1 );
1929 }
1930 if( node == NULL )
1931 {
1932 libcerror_error_set(
1933 error,
1934 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1935 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1936 "%s: invalid B-tree node.",
1937 function );
1938
1939 return( -1 );
1940 }
1941 if( node->descriptor == NULL )
1942 {
1943 libcerror_error_set(
1944 error,
1945 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1946 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1947 "%s: invalid B-tree node - missing descriptor.",
1948 function );
1949
1950 return( -1 );
1951 }
1952 if( directory_entry == NULL )
1953 {
1954 libcerror_error_set(
1955 error,
1956 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1957 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1958 "%s: invalid directory entry.",
1959 function );
1960
1961 return( -1 );
1962 }
1963 if( ( recursion_depth < 0 )
1964 || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
1965 {
1966 libcerror_error_set(
1967 error,
1968 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1969 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1970 "%s: invalid recursion depth value out of bounds.",
1971 function );
1972
1973 return( -1 );
1974 }
1975 is_branch_node = libfshfs_btree_node_is_branch_node(
1976 node,
1977 error );
1978
1979 if( is_branch_node == -1 )
1980 {
1981 libcerror_error_set(
1982 error,
1983 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1984 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1985 "%s: unable to determine if B-tree node is a branch node.",
1986 function );
1987
1988 goto on_error;
1989 }
1990 else if( is_branch_node == 0 )
1991 {
1992 libcerror_error_set(
1993 error,
1994 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1995 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1996 "%s: invalid node - not a branch node.",
1997 function );
1998
1999 goto on_error;
2000 }
2001 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
2002 node,
2003 0,
2004 &last_node_key,
2005 error ) == -1 )
2006 {
2007 libcerror_error_set(
2008 error,
2009 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2010 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2011 "%s: unable to retrieve catalog B-tree key: 0.",
2012 function );
2013
2014 goto on_error;
2015 }
2016 node_key = last_node_key;
2017
2018 for( record_index = 1;
2019 record_index <= node->descriptor->number_of_records;
2020 record_index++ )
2021 {
2022 if( record_index < node->descriptor->number_of_records )
2023 {
2024 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
2025 node,
2026 record_index,
2027 &node_key,
2028 error ) == -1 )
2029 {
2030 libcerror_error_set(
2031 error,
2032 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2033 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2034 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
2035 function,
2036 record_index );
2037
2038 goto on_error;
2039 }
2040 }
2041 if( node_key == NULL )
2042 {
2043 libcerror_error_set(
2044 error,
2045 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2046 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2047 "%s: missing catalog B-tree key: %" PRIu16 ".",
2048 function,
2049 record_index );
2050
2051 goto on_error;
2052 }
2053 if( ( record_index == node->descriptor->number_of_records )
2054 || ( node_key->parent_identifier >= parent_identifier ) )
2055 {
2056 if( libfshfs_catalog_btree_file_get_sub_node_number_from_key(
2057 last_node_key,
2058 &sub_node_number,
2059 error ) != 1 )
2060 {
2061 libcerror_error_set(
2062 error,
2063 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2064 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2065 "%s: unable to retrieve sub node number from catalog B-Tree key.",
2066 function );
2067
2068 goto on_error;
2069 }
2070 #if defined( HAVE_DEBUG_OUTPUT )
2071 if( libcnotify_verbose != 0 )
2072 {
2073 libcnotify_printf(
2074 "%s: B-tree sub node number\t: %" PRIu32 "\n",
2075 function,
2076 sub_node_number );
2077
2078 libcnotify_printf(
2079 "\n" );
2080 }
2081 #endif
2082 if( libfshfs_btree_file_get_node_by_number(
2083 btree_file,
2084 file_io_handle,
2085 sub_node_number,
2086 &sub_node,
2087 recursion_depth,
2088 error ) == -1 )
2089 {
2090 libcerror_error_set(
2091 error,
2092 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2093 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2094 "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
2095 function,
2096 sub_node_number );
2097
2098 goto on_error;
2099 }
2100 if( libfshfs_btree_node_get_node_type(
2101 sub_node,
2102 &node_type,
2103 error ) != 1 )
2104 {
2105 libcerror_error_set(
2106 error,
2107 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2108 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2109 "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
2110 function,
2111 sub_node_number );
2112
2113 goto on_error;
2114 }
2115 if( node_type == 0x00 )
2116 {
2117 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name(
2118 btree_file,
2119 file_io_handle,
2120 sub_node,
2121 parent_identifier,
2122 utf8_string,
2123 utf8_string_length,
2124 use_case_folding,
2125 directory_entry,
2126 recursion_depth + 1,
2127 error );
2128 }
2129 else if( node_type == 0xff )
2130 {
2131 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name(
2132 btree_file,
2133 sub_node,
2134 parent_identifier,
2135 utf8_string,
2136 utf8_string_length,
2137 use_case_folding,
2138 directory_entry,
2139 error );
2140 }
2141 if( result == -1 )
2142 {
2143 libcerror_error_set(
2144 error,
2145 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2146 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2147 "%s: unable to retrieve directory entry from catalog B-tree node: %" PRIu32 ".",
2148 function,
2149 sub_node_number );
2150
2151 goto on_error;
2152 }
2153 if( ( result == 1 )
2154 || ( node_key->parent_identifier > parent_identifier ) )
2155 {
2156 break;
2157 }
2158 }
2159 last_node_key = node_key;
2160 }
2161 return( result );
2162
2163 on_error:
2164 if( *directory_entry != NULL )
2165 {
2166 libfshfs_directory_entry_free(
2167 directory_entry,
2168 NULL );
2169 }
2170 return( -1 );
2171 }
2172
2173 /* Retrieves a directory entry for an UTF-8 encoded name from the catalog B-tree file
2174 * Returns 1 if successful, 0 if not found or -1 on error
2175 */
libfshfs_catalog_btree_file_get_directory_entry_by_utf8_name(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)2176 int libfshfs_catalog_btree_file_get_directory_entry_by_utf8_name(
2177 libfshfs_btree_file_t *btree_file,
2178 libbfio_handle_t *file_io_handle,
2179 uint32_t parent_identifier,
2180 const uint8_t *utf8_string,
2181 size_t utf8_string_length,
2182 uint8_t use_case_folding,
2183 libfshfs_directory_entry_t **directory_entry,
2184 libcerror_error_t **error )
2185 {
2186 libfshfs_btree_node_t *root_node = NULL;
2187 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_by_utf8_name";
2188 uint8_t node_type = 0;
2189 int result = 0;
2190
2191 if( libfshfs_btree_file_get_root_node(
2192 btree_file,
2193 file_io_handle,
2194 &root_node,
2195 0,
2196 error ) == -1 )
2197 {
2198 libcerror_error_set(
2199 error,
2200 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2201 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2202 "%s: unable to retrieve B-tree root node.",
2203 function );
2204
2205 return( -1 );
2206 }
2207 if( libfshfs_btree_node_get_node_type(
2208 root_node,
2209 &node_type,
2210 error ) != 1 )
2211 {
2212 libcerror_error_set(
2213 error,
2214 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2215 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2216 "%s: unable to determine if B-tree root node type.",
2217 function );
2218
2219 return( -1 );
2220 }
2221 if( node_type == 0x00 )
2222 {
2223 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name(
2224 btree_file,
2225 file_io_handle,
2226 root_node,
2227 parent_identifier,
2228 utf8_string,
2229 utf8_string_length,
2230 use_case_folding,
2231 directory_entry,
2232 1,
2233 error );
2234 }
2235 else if( node_type == 0xff )
2236 {
2237 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name(
2238 btree_file,
2239 root_node,
2240 parent_identifier,
2241 utf8_string,
2242 utf8_string_length,
2243 use_case_folding,
2244 directory_entry,
2245 error );
2246 }
2247 if( result == -1 )
2248 {
2249 libcerror_error_set(
2250 error,
2251 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2252 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2253 "%s: unable to retrieve directory entry from catalog B-tree root node.",
2254 function );
2255
2256 return( -1 );
2257 }
2258 return( result );
2259 }
2260
2261 /* Retrieves a directory entry for an UTF-8 encoded path from the catalog B-tree file
2262 * Returns 1 if successful, 0 if not found or -1 on error
2263 */
libfshfs_catalog_btree_file_get_directory_entry_by_utf8_path(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)2264 int libfshfs_catalog_btree_file_get_directory_entry_by_utf8_path(
2265 libfshfs_btree_file_t *btree_file,
2266 libbfio_handle_t *file_io_handle,
2267 const uint8_t *utf8_string,
2268 size_t utf8_string_length,
2269 uint8_t use_case_folding,
2270 libfshfs_directory_entry_t **directory_entry,
2271 libcerror_error_t **error )
2272 {
2273 libfshfs_btree_node_t *root_node = NULL;
2274 libfshfs_directory_entry_t *safe_directory_entry = NULL;
2275 const uint8_t *utf8_string_segment = NULL;
2276 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_by_utf8_path";
2277 libuna_unicode_character_t unicode_character = 0;
2278 size_t utf8_string_index = 0;
2279 size_t utf8_string_segment_length = 0;
2280 uint32_t lookup_identifier = 0;
2281 uint8_t node_type = 0;
2282 int result = 0;
2283
2284 if( btree_file == NULL )
2285 {
2286 libcerror_error_set(
2287 error,
2288 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2289 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2290 "%s: invalid B-tree file.",
2291 function );
2292
2293 return( -1 );
2294 }
2295 if( utf8_string == NULL )
2296 {
2297 libcerror_error_set(
2298 error,
2299 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2300 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2301 "%s: invalid UTF-8 string.",
2302 function );
2303
2304 return( -1 );
2305 }
2306 if( utf8_string_length > (size_t) SSIZE_MAX )
2307 {
2308 libcerror_error_set(
2309 error,
2310 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2311 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
2312 "%s: invalid UTF-8 string length value exceeds maximum.",
2313 function );
2314
2315 return( -1 );
2316 }
2317 if( directory_entry == NULL )
2318 {
2319 libcerror_error_set(
2320 error,
2321 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2322 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2323 "%s: invalid directory entry.",
2324 function );
2325
2326 return( -1 );
2327 }
2328 if( libfshfs_btree_file_get_root_node(
2329 btree_file,
2330 file_io_handle,
2331 &root_node,
2332 0,
2333 error ) == -1 )
2334 {
2335 libcerror_error_set(
2336 error,
2337 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2338 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2339 "%s: unable to retrieve B-tree root node.",
2340 function );
2341
2342 goto on_error;
2343 }
2344 if( libfshfs_btree_node_get_node_type(
2345 root_node,
2346 &node_type,
2347 error ) != 1 )
2348 {
2349 libcerror_error_set(
2350 error,
2351 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2352 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2353 "%s: unable to determine if B-tree root node type.",
2354 function );
2355
2356 goto on_error;
2357 }
2358 lookup_identifier = LIBFSHFS_ROOT_DIRECTORY_IDENTIFIER;
2359
2360 if( utf8_string_length > 0 )
2361 {
2362 /* Ignore a leading separator
2363 */
2364 if( utf8_string[ utf8_string_index ] == (uint8_t) LIBFSHFS_SEPARATOR )
2365 {
2366 utf8_string_index++;
2367 }
2368 }
2369 if( ( utf8_string_length == 0 )
2370 || ( utf8_string_length == 1 ) )
2371 {
2372 /* TODO optimize this */
2373 result = libfshfs_catalog_btree_file_get_directory_entry_by_identifier(
2374 btree_file,
2375 file_io_handle,
2376 LIBFSHFS_ROOT_DIRECTORY_IDENTIFIER,
2377 &safe_directory_entry,
2378 error );
2379
2380 if( result == -1 )
2381 {
2382 libcerror_error_set(
2383 error,
2384 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2385 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2386 "%s: unable to retrieve root directory entry from catalog B-tree file.",
2387 function );
2388
2389 goto on_error;
2390 }
2391 }
2392 else while( utf8_string_index < utf8_string_length )
2393 {
2394 utf8_string_segment = &( utf8_string[ utf8_string_index ] );
2395 utf8_string_segment_length = utf8_string_index;
2396
2397 while( utf8_string_index < utf8_string_length )
2398 {
2399 if( libuna_unicode_character_copy_from_utf8(
2400 &unicode_character,
2401 utf8_string,
2402 utf8_string_length,
2403 &utf8_string_index,
2404 error ) != 1 )
2405 {
2406 libcerror_error_set(
2407 error,
2408 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2409 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
2410 "%s: unable to copy UTF-8 string to Unicode character.",
2411 function );
2412
2413 goto on_error;
2414 }
2415 if( ( unicode_character == (libuna_unicode_character_t) LIBFSHFS_SEPARATOR )
2416 || ( unicode_character == 0 ) )
2417 {
2418 utf8_string_segment_length += 1;
2419
2420 break;
2421 }
2422 }
2423 utf8_string_segment_length = utf8_string_index - utf8_string_segment_length;
2424
2425 if( utf8_string_segment_length == 0 )
2426 {
2427 result = 0;
2428 }
2429 else
2430 {
2431 if( safe_directory_entry != NULL )
2432 {
2433 if( libfshfs_directory_entry_free(
2434 &safe_directory_entry,
2435 error ) != 1 )
2436 {
2437 libcerror_error_set(
2438 error,
2439 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2440 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2441 "%s: unable to free directory entry.",
2442 function );
2443
2444 goto on_error;
2445 }
2446 }
2447 if( node_type == 0x00 )
2448 {
2449 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf8_name(
2450 btree_file,
2451 file_io_handle,
2452 root_node,
2453 lookup_identifier,
2454 utf8_string_segment,
2455 utf8_string_segment_length,
2456 use_case_folding,
2457 &safe_directory_entry,
2458 1,
2459 error );
2460 }
2461 else if( node_type == 0xff )
2462 {
2463 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf8_name(
2464 btree_file,
2465 root_node,
2466 lookup_identifier,
2467 utf8_string_segment,
2468 utf8_string_segment_length,
2469 use_case_folding,
2470 &safe_directory_entry,
2471 error );
2472 }
2473 }
2474 if( result == -1 )
2475 {
2476 libcerror_error_set(
2477 error,
2478 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2479 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2480 "%s: unable to retrieve directory entry by name.",
2481 function );
2482
2483 goto on_error;
2484 }
2485 else if( result == 0 )
2486 {
2487 break;
2488 }
2489 if( libfshfs_directory_entry_get_identifier(
2490 safe_directory_entry,
2491 &lookup_identifier,
2492 error ) != 1 )
2493 {
2494 libcerror_error_set(
2495 error,
2496 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2497 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2498 "%s: unable to retrieve directory entry identifier.",
2499 function );
2500
2501 goto on_error;
2502 }
2503 }
2504 if( result != 0 )
2505 {
2506 *directory_entry = safe_directory_entry;
2507 }
2508 return( result );
2509
2510 on_error:
2511 if( *directory_entry != NULL )
2512 {
2513 libfshfs_directory_entry_free(
2514 directory_entry,
2515 NULL );
2516 }
2517 return( -1 );
2518 }
2519
2520 /* Retrieves a directory entry for an UTF-16 encoded name from the catalog B-tree leaf node
2521 * Returns 1 if successful, 0 if not found or -1 on error
2522 */
libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name(libfshfs_btree_file_t * btree_file,libfshfs_btree_node_t * node,uint32_t parent_identifier,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)2523 int libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name(
2524 libfshfs_btree_file_t *btree_file,
2525 libfshfs_btree_node_t *node,
2526 uint32_t parent_identifier,
2527 const uint16_t *utf16_string,
2528 size_t utf16_string_length,
2529 uint8_t use_case_folding,
2530 libfshfs_directory_entry_t **directory_entry,
2531 libcerror_error_t **error )
2532 {
2533 libfshfs_catalog_btree_key_t *node_key = NULL;
2534 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name";
2535 uint16_t record_index = 0;
2536 uint16_t record_type = 0;
2537 int compare_result = 0;
2538 int is_leaf_node = 0;
2539 int result = 0;
2540
2541 if( btree_file == NULL )
2542 {
2543 libcerror_error_set(
2544 error,
2545 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2546 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2547 "%s: invalid B-tree file.",
2548 function );
2549
2550 return( -1 );
2551 }
2552 if( node == NULL )
2553 {
2554 libcerror_error_set(
2555 error,
2556 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2557 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2558 "%s: invalid B-tree node.",
2559 function );
2560
2561 return( -1 );
2562 }
2563 if( node->descriptor == NULL )
2564 {
2565 libcerror_error_set(
2566 error,
2567 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2568 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2569 "%s: invalid B-tree node - missing descriptor.",
2570 function );
2571
2572 return( -1 );
2573 }
2574 if( directory_entry == NULL )
2575 {
2576 libcerror_error_set(
2577 error,
2578 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2579 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2580 "%s: invalid directory entry.",
2581 function );
2582
2583 return( -1 );
2584 }
2585 is_leaf_node = libfshfs_btree_node_is_leaf_node(
2586 node,
2587 error );
2588
2589 if( is_leaf_node == -1 )
2590 {
2591 libcerror_error_set(
2592 error,
2593 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2594 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2595 "%s: unable to determine if B-tree node is a leaf node.",
2596 function );
2597
2598 goto on_error;
2599 }
2600 else if( is_leaf_node == 0 )
2601 {
2602 libcerror_error_set(
2603 error,
2604 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2605 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2606 "%s: invalid node - not a leaf node.",
2607 function );
2608
2609 goto on_error;
2610 }
2611 for( record_index = 0;
2612 record_index < node->descriptor->number_of_records;
2613 record_index++ )
2614 {
2615 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
2616 node,
2617 record_index,
2618 &node_key,
2619 error ) == -1 )
2620 {
2621 libcerror_error_set(
2622 error,
2623 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2624 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2625 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
2626 function,
2627 record_index );
2628
2629 goto on_error;
2630 }
2631 if( node_key == NULL )
2632 {
2633 libcerror_error_set(
2634 error,
2635 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2636 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2637 "%s: missing catalog B-tree key: %" PRIu16 ".",
2638 function,
2639 record_index );
2640
2641 goto on_error;
2642 }
2643 if( node_key->parent_identifier == parent_identifier )
2644 {
2645 if( node_key->record_data_size < 2 )
2646 {
2647 libcerror_error_set(
2648 error,
2649 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2650 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2651 "%s: invalid catalog B-tree key: %" PRIu16 " - record data size value out of bounds.",
2652 function,
2653 record_index );
2654
2655 goto on_error;
2656 }
2657 byte_stream_copy_to_uint16_big_endian(
2658 node_key->record_data,
2659 record_type );
2660
2661 switch( record_type )
2662 {
2663 case LIBFSHFS_RECORD_TYPE_HFSPLUS_DIRECTORY_RECORD:
2664 case LIBFSHFS_RECORD_TYPE_HFSPLUS_FILE_RECORD:
2665 case LIBFSHFS_RECORD_TYPE_HFS_DIRECTORY_RECORD:
2666 case LIBFSHFS_RECORD_TYPE_HFS_FILE_RECORD:
2667 compare_result = libfshfs_catalog_btree_key_compare_name_with_utf16_string(
2668 node_key,
2669 utf16_string,
2670 utf16_string_length,
2671 use_case_folding,
2672 error );
2673
2674 if( compare_result == -1 )
2675 {
2676 libcerror_error_set(
2677 error,
2678 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2679 LIBCERROR_RUNTIME_ERROR_GENERIC,
2680 "%s: unable to compare UTF-16 string with catalog B-tree key name.",
2681 function );
2682
2683 goto on_error;
2684 }
2685 break;
2686
2687 default:
2688 compare_result = LIBUNA_COMPARE_LESS;
2689 break;
2690 }
2691 if( compare_result == LIBUNA_COMPARE_EQUAL )
2692 {
2693 result = libfshfs_catalog_btree_file_get_directory_entry_from_key(
2694 node_key,
2695 directory_entry,
2696 error );
2697
2698 if( result == -1 )
2699 {
2700 libcerror_error_set(
2701 error,
2702 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2703 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2704 "%s: unable to retrieve directory entry from record data.",
2705 function );
2706
2707 goto on_error;
2708 }
2709 }
2710 }
2711 if( ( result == 1 )
2712 || ( node_key->parent_identifier > parent_identifier ) )
2713 {
2714 break;
2715 }
2716 }
2717 return( result );
2718
2719 on_error:
2720 if( *directory_entry != NULL )
2721 {
2722 libfshfs_directory_entry_free(
2723 directory_entry,
2724 NULL );
2725 }
2726 return( -1 );
2727 }
2728
2729 /* Retrieves a directory entry for an UTF-16 encoded name from the catalog B-tree branch node
2730 * Returns 1 if successful, 0 if not found or -1 on error
2731 */
libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,libfshfs_btree_node_t * node,uint32_t parent_identifier,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,int recursion_depth,libcerror_error_t ** error)2732 int libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name(
2733 libfshfs_btree_file_t *btree_file,
2734 libbfio_handle_t *file_io_handle,
2735 libfshfs_btree_node_t *node,
2736 uint32_t parent_identifier,
2737 const uint16_t *utf16_string,
2738 size_t utf16_string_length,
2739 uint8_t use_case_folding,
2740 libfshfs_directory_entry_t **directory_entry,
2741 int recursion_depth,
2742 libcerror_error_t **error )
2743 {
2744 libfshfs_btree_node_t *sub_node = NULL;
2745 libfshfs_catalog_btree_key_t *last_node_key = NULL;
2746 libfshfs_catalog_btree_key_t *node_key = NULL;
2747 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name";
2748 uint32_t sub_node_number = 0;
2749 uint16_t record_index = 0;
2750 uint8_t node_type = 0;
2751 int is_branch_node = 0;
2752 int result = 0;
2753
2754 if( btree_file == NULL )
2755 {
2756 libcerror_error_set(
2757 error,
2758 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2759 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2760 "%s: invalid B-tree file.",
2761 function );
2762
2763 return( -1 );
2764 }
2765 if( node == NULL )
2766 {
2767 libcerror_error_set(
2768 error,
2769 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2770 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2771 "%s: invalid B-tree node.",
2772 function );
2773
2774 return( -1 );
2775 }
2776 if( node->descriptor == NULL )
2777 {
2778 libcerror_error_set(
2779 error,
2780 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2781 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2782 "%s: invalid B-tree node - missing descriptor.",
2783 function );
2784
2785 return( -1 );
2786 }
2787 if( directory_entry == NULL )
2788 {
2789 libcerror_error_set(
2790 error,
2791 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2792 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2793 "%s: invalid directory entry.",
2794 function );
2795
2796 return( -1 );
2797 }
2798 if( ( recursion_depth < 0 )
2799 || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
2800 {
2801 libcerror_error_set(
2802 error,
2803 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2804 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2805 "%s: invalid recursion depth value out of bounds.",
2806 function );
2807
2808 return( -1 );
2809 }
2810 is_branch_node = libfshfs_btree_node_is_branch_node(
2811 node,
2812 error );
2813
2814 if( is_branch_node == -1 )
2815 {
2816 libcerror_error_set(
2817 error,
2818 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2819 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2820 "%s: unable to determine if B-tree node is a branch node.",
2821 function );
2822
2823 goto on_error;
2824 }
2825 else if( is_branch_node == 0 )
2826 {
2827 libcerror_error_set(
2828 error,
2829 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2830 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
2831 "%s: invalid node - not a branch node.",
2832 function );
2833
2834 goto on_error;
2835 }
2836 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
2837 node,
2838 0,
2839 &last_node_key,
2840 error ) == -1 )
2841 {
2842 libcerror_error_set(
2843 error,
2844 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2845 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2846 "%s: unable to retrieve catalog B-tree key: 0.",
2847 function );
2848
2849 goto on_error;
2850 }
2851 node_key = last_node_key;
2852
2853 for( record_index = 1;
2854 record_index <= node->descriptor->number_of_records;
2855 record_index++ )
2856 {
2857 if( record_index < node->descriptor->number_of_records )
2858 {
2859 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
2860 node,
2861 record_index,
2862 &node_key,
2863 error ) == -1 )
2864 {
2865 libcerror_error_set(
2866 error,
2867 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2868 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2869 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
2870 function,
2871 record_index );
2872
2873 goto on_error;
2874 }
2875 }
2876 if( node_key == NULL )
2877 {
2878 libcerror_error_set(
2879 error,
2880 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2881 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2882 "%s: missing catalog B-tree key: %" PRIu16 ".",
2883 function,
2884 record_index );
2885
2886 goto on_error;
2887 }
2888 if( ( record_index == node->descriptor->number_of_records )
2889 || ( node_key->parent_identifier >= parent_identifier ) )
2890 {
2891 if( libfshfs_catalog_btree_file_get_sub_node_number_from_key(
2892 last_node_key,
2893 &sub_node_number,
2894 error ) != 1 )
2895 {
2896 libcerror_error_set(
2897 error,
2898 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2899 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2900 "%s: unable to retrieve sub node number from catalog B-Tree key.",
2901 function );
2902
2903 goto on_error;
2904 }
2905 #if defined( HAVE_DEBUG_OUTPUT )
2906 if( libcnotify_verbose != 0 )
2907 {
2908 libcnotify_printf(
2909 "%s: B-tree sub node number\t: %" PRIu32 "\n",
2910 function,
2911 sub_node_number );
2912
2913 libcnotify_printf(
2914 "\n" );
2915 }
2916 #endif
2917 if( libfshfs_btree_file_get_node_by_number(
2918 btree_file,
2919 file_io_handle,
2920 sub_node_number,
2921 &sub_node,
2922 recursion_depth,
2923 error ) == -1 )
2924 {
2925 libcerror_error_set(
2926 error,
2927 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2928 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2929 "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
2930 function,
2931 sub_node_number );
2932
2933 goto on_error;
2934 }
2935 if( libfshfs_btree_node_get_node_type(
2936 sub_node,
2937 &node_type,
2938 error ) != 1 )
2939 {
2940 libcerror_error_set(
2941 error,
2942 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2943 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2944 "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
2945 function,
2946 sub_node_number );
2947
2948 goto on_error;
2949 }
2950 if( node_type == 0x00 )
2951 {
2952 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name(
2953 btree_file,
2954 file_io_handle,
2955 sub_node,
2956 parent_identifier,
2957 utf16_string,
2958 utf16_string_length,
2959 use_case_folding,
2960 directory_entry,
2961 recursion_depth + 1,
2962 error );
2963 }
2964 else if( node_type == 0xff )
2965 {
2966 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name(
2967 btree_file,
2968 sub_node,
2969 parent_identifier,
2970 utf16_string,
2971 utf16_string_length,
2972 use_case_folding,
2973 directory_entry,
2974 error );
2975 }
2976 if( result == -1 )
2977 {
2978 libcerror_error_set(
2979 error,
2980 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2981 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2982 "%s: unable to retrieve directory entry from catalog B-tree node: %" PRIu32 ".",
2983 function,
2984 sub_node_number );
2985
2986 goto on_error;
2987 }
2988 if( ( result == 1 )
2989 || ( node_key->parent_identifier > parent_identifier ) )
2990 {
2991 break;
2992 }
2993 }
2994 last_node_key = node_key;
2995 }
2996 return( result );
2997
2998 on_error:
2999 if( *directory_entry != NULL )
3000 {
3001 libfshfs_directory_entry_free(
3002 directory_entry,
3003 NULL );
3004 }
3005 return( -1 );
3006 }
3007
3008 /* Retrieves a directory entry for an UTF-16 encoded name from the catalog B-tree file
3009 * Returns 1 if successful, 0 if not found or -1 on error
3010 */
libfshfs_catalog_btree_file_get_directory_entry_by_utf16_name(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)3011 int libfshfs_catalog_btree_file_get_directory_entry_by_utf16_name(
3012 libfshfs_btree_file_t *btree_file,
3013 libbfio_handle_t *file_io_handle,
3014 uint32_t parent_identifier,
3015 const uint16_t *utf16_string,
3016 size_t utf16_string_length,
3017 uint8_t use_case_folding,
3018 libfshfs_directory_entry_t **directory_entry,
3019 libcerror_error_t **error )
3020 {
3021 libfshfs_btree_node_t *root_node = NULL;
3022 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_by_utf16_name";
3023 uint8_t node_type = 0;
3024 int result = 0;
3025
3026 if( libfshfs_btree_file_get_root_node(
3027 btree_file,
3028 file_io_handle,
3029 &root_node,
3030 0,
3031 error ) == -1 )
3032 {
3033 libcerror_error_set(
3034 error,
3035 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3036 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3037 "%s: unable to retrieve B-tree root node.",
3038 function );
3039
3040 return( -1 );
3041 }
3042 if( libfshfs_btree_node_get_node_type(
3043 root_node,
3044 &node_type,
3045 error ) != 1 )
3046 {
3047 libcerror_error_set(
3048 error,
3049 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3050 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3051 "%s: unable to determine if B-tree root node type.",
3052 function );
3053
3054 return( -1 );
3055 }
3056 if( node_type == 0x00 )
3057 {
3058 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name(
3059 btree_file,
3060 file_io_handle,
3061 root_node,
3062 parent_identifier,
3063 utf16_string,
3064 utf16_string_length,
3065 use_case_folding,
3066 directory_entry,
3067 1,
3068 error );
3069 }
3070 else if( node_type == 0xff )
3071 {
3072 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name(
3073 btree_file,
3074 root_node,
3075 parent_identifier,
3076 utf16_string,
3077 utf16_string_length,
3078 use_case_folding,
3079 directory_entry,
3080 error );
3081 }
3082 if( result == -1 )
3083 {
3084 libcerror_error_set(
3085 error,
3086 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3087 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3088 "%s: unable to retrieve directory entry from catalog B-tree root node.",
3089 function );
3090
3091 return( -1 );
3092 }
3093 return( result );
3094 }
3095
3096 /* Retrieves a directory entry for an UTF-16 encoded path from the catalog B-tree file
3097 * Returns 1 if successful, 0 if not found or -1 on error
3098 */
libfshfs_catalog_btree_file_get_directory_entry_by_utf16_path(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)3099 int libfshfs_catalog_btree_file_get_directory_entry_by_utf16_path(
3100 libfshfs_btree_file_t *btree_file,
3101 libbfio_handle_t *file_io_handle,
3102 const uint16_t *utf16_string,
3103 size_t utf16_string_length,
3104 uint8_t use_case_folding,
3105 libfshfs_directory_entry_t **directory_entry,
3106 libcerror_error_t **error )
3107 {
3108 libfshfs_btree_node_t *root_node = NULL;
3109 libfshfs_directory_entry_t *safe_directory_entry = NULL;
3110 const uint16_t *utf16_string_segment = NULL;
3111 static char *function = "libfshfs_catalog_btree_file_get_directory_entry_by_utf16_path";
3112 libuna_unicode_character_t unicode_character = 0;
3113 size_t utf16_string_index = 0;
3114 size_t utf16_string_segment_length = 0;
3115 uint32_t lookup_identifier = 0;
3116 uint8_t node_type = 0;
3117 int result = 0;
3118
3119 if( btree_file == NULL )
3120 {
3121 libcerror_error_set(
3122 error,
3123 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3124 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3125 "%s: invalid B-tree file.",
3126 function );
3127
3128 return( -1 );
3129 }
3130 if( utf16_string == NULL )
3131 {
3132 libcerror_error_set(
3133 error,
3134 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3135 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3136 "%s: invalid UTF-16 string.",
3137 function );
3138
3139 return( -1 );
3140 }
3141 if( utf16_string_length > (size_t) SSIZE_MAX )
3142 {
3143 libcerror_error_set(
3144 error,
3145 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3146 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
3147 "%s: invalid UTF-16 string length value exceeds maximum.",
3148 function );
3149
3150 return( -1 );
3151 }
3152 if( directory_entry == NULL )
3153 {
3154 libcerror_error_set(
3155 error,
3156 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3157 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3158 "%s: invalid directory entry.",
3159 function );
3160
3161 return( -1 );
3162 }
3163 if( libfshfs_btree_file_get_root_node(
3164 btree_file,
3165 file_io_handle,
3166 &root_node,
3167 0,
3168 error ) == -1 )
3169 {
3170 libcerror_error_set(
3171 error,
3172 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3173 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3174 "%s: unable to retrieve B-tree root node.",
3175 function );
3176
3177 goto on_error;
3178 }
3179 if( libfshfs_btree_node_get_node_type(
3180 root_node,
3181 &node_type,
3182 error ) != 1 )
3183 {
3184 libcerror_error_set(
3185 error,
3186 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3187 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3188 "%s: unable to determine if B-tree root node type.",
3189 function );
3190
3191 goto on_error;
3192 }
3193 lookup_identifier = LIBFSHFS_ROOT_DIRECTORY_IDENTIFIER;
3194
3195 if( utf16_string_length > 0 )
3196 {
3197 /* Ignore a leading separator
3198 */
3199 if( utf16_string[ utf16_string_index ] == (uint16_t) LIBFSHFS_SEPARATOR )
3200 {
3201 utf16_string_index++;
3202 }
3203 }
3204 if( ( utf16_string_length == 0 )
3205 || ( utf16_string_length == 1 ) )
3206 {
3207 /* TODO optimize this */
3208 result = libfshfs_catalog_btree_file_get_directory_entry_by_identifier(
3209 btree_file,
3210 file_io_handle,
3211 LIBFSHFS_ROOT_DIRECTORY_IDENTIFIER,
3212 &safe_directory_entry,
3213 error );
3214
3215 if( result == -1 )
3216 {
3217 libcerror_error_set(
3218 error,
3219 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3220 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3221 "%s: unable to retrieve root directory entry from catalog B-tree file.",
3222 function );
3223
3224 goto on_error;
3225 }
3226 }
3227 else while( utf16_string_index < utf16_string_length )
3228 {
3229 utf16_string_segment = &( utf16_string[ utf16_string_index ] );
3230 utf16_string_segment_length = utf16_string_index;
3231
3232 while( utf16_string_index < utf16_string_length )
3233 {
3234 if( libuna_unicode_character_copy_from_utf16(
3235 &unicode_character,
3236 utf16_string,
3237 utf16_string_length,
3238 &utf16_string_index,
3239 error ) != 1 )
3240 {
3241 libcerror_error_set(
3242 error,
3243 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3244 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
3245 "%s: unable to copy UTF-16 string to Unicode character.",
3246 function );
3247
3248 goto on_error;
3249 }
3250 if( ( unicode_character == (libuna_unicode_character_t) LIBFSHFS_SEPARATOR )
3251 || ( unicode_character == 0 ) )
3252 {
3253 utf16_string_segment_length += 1;
3254
3255 break;
3256 }
3257 }
3258 utf16_string_segment_length = utf16_string_index - utf16_string_segment_length;
3259
3260 if( utf16_string_segment_length == 0 )
3261 {
3262 result = 0;
3263 }
3264 else
3265 {
3266 if( safe_directory_entry != NULL )
3267 {
3268 if( libfshfs_directory_entry_free(
3269 &safe_directory_entry,
3270 error ) != 1 )
3271 {
3272 libcerror_error_set(
3273 error,
3274 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3275 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
3276 "%s: unable to free directory entry.",
3277 function );
3278
3279 goto on_error;
3280 }
3281 }
3282 if( node_type == 0x00 )
3283 {
3284 result = libfshfs_catalog_btree_file_get_directory_entry_from_branch_node_by_utf16_name(
3285 btree_file,
3286 file_io_handle,
3287 root_node,
3288 lookup_identifier,
3289 utf16_string_segment,
3290 utf16_string_segment_length,
3291 use_case_folding,
3292 &safe_directory_entry,
3293 1,
3294 error );
3295 }
3296 else if( node_type == 0xff )
3297 {
3298 result = libfshfs_catalog_btree_file_get_directory_entry_from_leaf_node_by_utf16_name(
3299 btree_file,
3300 root_node,
3301 lookup_identifier,
3302 utf16_string_segment,
3303 utf16_string_segment_length,
3304 use_case_folding,
3305 &safe_directory_entry,
3306 error );
3307 }
3308 }
3309 if( result == -1 )
3310 {
3311 libcerror_error_set(
3312 error,
3313 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3314 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3315 "%s: unable to retrieve directory entry by name.",
3316 function );
3317
3318 goto on_error;
3319 }
3320 else if( result == 0 )
3321 {
3322 break;
3323 }
3324 if( libfshfs_directory_entry_get_identifier(
3325 safe_directory_entry,
3326 &lookup_identifier,
3327 error ) != 1 )
3328 {
3329 libcerror_error_set(
3330 error,
3331 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3332 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3333 "%s: unable to retrieve directory entry identifier.",
3334 function );
3335
3336 goto on_error;
3337 }
3338 }
3339 if( result != 0 )
3340 {
3341 *directory_entry = safe_directory_entry;
3342 }
3343 return( result );
3344
3345 on_error:
3346 if( *directory_entry != NULL )
3347 {
3348 libfshfs_directory_entry_free(
3349 directory_entry,
3350 NULL );
3351 }
3352 return( -1 );
3353 }
3354
3355 /* Retrieves directory entries for a specific parent identifier from the catalog B-tree leaf node
3356 * Returns 1 if successful or -1 on error
3357 */
libfshfs_catalog_btree_file_get_directory_entries_from_leaf_node(libfshfs_btree_file_t * btree_file,libfshfs_btree_node_t * node,uint32_t parent_identifier,libcdata_array_t * directory_entries,libcerror_error_t ** error)3358 int libfshfs_catalog_btree_file_get_directory_entries_from_leaf_node(
3359 libfshfs_btree_file_t *btree_file,
3360 libfshfs_btree_node_t *node,
3361 uint32_t parent_identifier,
3362 libcdata_array_t *directory_entries,
3363 libcerror_error_t **error )
3364 {
3365 libfshfs_catalog_btree_key_t *node_key = NULL;
3366 libfshfs_directory_entry_t *directory_entry = NULL;
3367 static char *function = "libfshfs_catalog_btree_file_get_directory_entries_from_leaf_node";
3368 uint16_t record_index = 0;
3369 int entry_index = 0;
3370 int is_leaf_node = 0;
3371 int result = 0;
3372
3373 if( btree_file == NULL )
3374 {
3375 libcerror_error_set(
3376 error,
3377 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3378 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3379 "%s: invalid B-tree file.",
3380 function );
3381
3382 return( -1 );
3383 }
3384 if( node == NULL )
3385 {
3386 libcerror_error_set(
3387 error,
3388 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3389 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3390 "%s: invalid B-tree node.",
3391 function );
3392
3393 return( -1 );
3394 }
3395 if( node->descriptor == NULL )
3396 {
3397 libcerror_error_set(
3398 error,
3399 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3400 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3401 "%s: invalid B-tree node - missing descriptor.",
3402 function );
3403
3404 return( -1 );
3405 }
3406 is_leaf_node = libfshfs_btree_node_is_leaf_node(
3407 node,
3408 error );
3409
3410 if( is_leaf_node == -1 )
3411 {
3412 libcerror_error_set(
3413 error,
3414 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3415 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3416 "%s: unable to determine if B-tree node is a leaf node.",
3417 function );
3418
3419 goto on_error;
3420 }
3421 else if( is_leaf_node == 0 )
3422 {
3423 libcerror_error_set(
3424 error,
3425 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3426 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3427 "%s: invalid node - not a leaf node.",
3428 function );
3429
3430 goto on_error;
3431 }
3432 for( record_index = 0;
3433 record_index < node->descriptor->number_of_records;
3434 record_index++ )
3435 {
3436 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
3437 node,
3438 record_index,
3439 &node_key,
3440 error ) == -1 )
3441 {
3442 libcerror_error_set(
3443 error,
3444 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3445 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3446 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
3447 function,
3448 record_index );
3449
3450 goto on_error;
3451 }
3452 if( node_key == NULL )
3453 {
3454 libcerror_error_set(
3455 error,
3456 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3457 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3458 "%s: missing catalog B-tree key: %" PRIu16 ".",
3459 function,
3460 record_index );
3461
3462 goto on_error;
3463 }
3464 if( node_key->parent_identifier == parent_identifier )
3465 {
3466 result = libfshfs_catalog_btree_file_get_directory_entry_from_key(
3467 node_key,
3468 &directory_entry,
3469 error );
3470
3471 if( result == -1 )
3472 {
3473 libcerror_error_set(
3474 error,
3475 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3476 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3477 "%s: unable to retrieve directory entry from record data.",
3478 function );
3479
3480 goto on_error;
3481 }
3482 else if( result != 0 )
3483 {
3484 if( libcdata_array_append_entry(
3485 directory_entries,
3486 &entry_index,
3487 (intptr_t *) directory_entry,
3488 error ) != 1 )
3489 {
3490 libcerror_error_set(
3491 error,
3492 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3493 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
3494 "%s: unable to append directory entry to array.",
3495 function );
3496
3497 goto on_error;
3498 }
3499 directory_entry = NULL;
3500 }
3501 }
3502 if( node_key->parent_identifier > parent_identifier )
3503 {
3504 break;
3505 }
3506 }
3507 return( 1 );
3508
3509 on_error:
3510 if( directory_entry != NULL )
3511 {
3512 libfshfs_directory_entry_free(
3513 &directory_entry,
3514 NULL );
3515 }
3516 libcdata_array_empty(
3517 directory_entries,
3518 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_directory_entry_free,
3519 NULL );
3520
3521 return( -1 );
3522 }
3523
3524 /* Retrieves directory entries for a specific parent identifier from the catalog B-tree branch node
3525 * Returns 1 if successful or -1 on error
3526 */
libfshfs_catalog_btree_file_get_directory_entries_from_branch_node(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,libfshfs_btree_node_t * node,uint32_t parent_identifier,libcdata_array_t * directory_entries,int recursion_depth,libcerror_error_t ** error)3527 int libfshfs_catalog_btree_file_get_directory_entries_from_branch_node(
3528 libfshfs_btree_file_t *btree_file,
3529 libbfio_handle_t *file_io_handle,
3530 libfshfs_btree_node_t *node,
3531 uint32_t parent_identifier,
3532 libcdata_array_t *directory_entries,
3533 int recursion_depth,
3534 libcerror_error_t **error )
3535 {
3536 libfshfs_btree_node_t *sub_node = NULL;
3537 libfshfs_catalog_btree_key_t *last_node_key = NULL;
3538 libfshfs_catalog_btree_key_t *node_key = NULL;
3539 static char *function = "libfshfs_catalog_btree_file_get_directory_entries_from_branch_node";
3540 uint32_t sub_node_number = 0;
3541 uint16_t record_index = 0;
3542 uint8_t node_type = 0;
3543 int is_branch_node = 0;
3544 int result = 0;
3545
3546 if( btree_file == NULL )
3547 {
3548 libcerror_error_set(
3549 error,
3550 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3551 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3552 "%s: invalid B-tree file.",
3553 function );
3554
3555 return( -1 );
3556 }
3557 if( node == NULL )
3558 {
3559 libcerror_error_set(
3560 error,
3561 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3562 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3563 "%s: invalid B-tree node.",
3564 function );
3565
3566 return( -1 );
3567 }
3568 if( node->descriptor == NULL )
3569 {
3570 libcerror_error_set(
3571 error,
3572 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3573 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3574 "%s: invalid B-tree node - missing descriptor.",
3575 function );
3576
3577 return( -1 );
3578 }
3579 if( ( recursion_depth < 0 )
3580 || ( recursion_depth > LIBFSHFS_MAXIMUM_BTREE_NODE_RECURSION_DEPTH ) )
3581 {
3582 libcerror_error_set(
3583 error,
3584 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3585 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3586 "%s: invalid recursion depth value out of bounds.",
3587 function );
3588
3589 return( -1 );
3590 }
3591 is_branch_node = libfshfs_btree_node_is_branch_node(
3592 node,
3593 error );
3594
3595 if( is_branch_node == -1 )
3596 {
3597 libcerror_error_set(
3598 error,
3599 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3600 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3601 "%s: unable to determine if B-tree node is a branch node.",
3602 function );
3603
3604 goto on_error;
3605 }
3606 else if( is_branch_node == 0 )
3607 {
3608 libcerror_error_set(
3609 error,
3610 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3611 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
3612 "%s: invalid node - not a branch node.",
3613 function );
3614
3615 goto on_error;
3616 }
3617 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
3618 node,
3619 0,
3620 &last_node_key,
3621 error ) == -1 )
3622 {
3623 libcerror_error_set(
3624 error,
3625 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3626 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3627 "%s: unable to retrieve catalog B-tree key: 0.",
3628 function );
3629
3630 goto on_error;
3631 }
3632 node_key = last_node_key;
3633
3634 for( record_index = 1;
3635 record_index <= node->descriptor->number_of_records;
3636 record_index++ )
3637 {
3638 if( record_index < node->descriptor->number_of_records )
3639 {
3640 if( libfshfs_catalog_btree_file_get_key_from_node_by_index(
3641 node,
3642 record_index,
3643 &node_key,
3644 error ) == -1 )
3645 {
3646 libcerror_error_set(
3647 error,
3648 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3649 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3650 "%s: unable to retrieve catalog B-tree key: %" PRIu16 ".",
3651 function,
3652 record_index );
3653
3654 goto on_error;
3655 }
3656 }
3657 if( node_key == NULL )
3658 {
3659 libcerror_error_set(
3660 error,
3661 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3662 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3663 "%s: missing catalog B-tree key: %" PRIu16 ".",
3664 function,
3665 record_index );
3666
3667 goto on_error;
3668 }
3669 if( ( record_index == node->descriptor->number_of_records )
3670 || ( node_key->parent_identifier >= parent_identifier ) )
3671 {
3672 if( libfshfs_catalog_btree_file_get_sub_node_number_from_key(
3673 last_node_key,
3674 &sub_node_number,
3675 error ) != 1 )
3676 {
3677 libcerror_error_set(
3678 error,
3679 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3680 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3681 "%s: unable to retrieve sub node number from catalog B-Tree key.",
3682 function );
3683
3684 goto on_error;
3685 }
3686 #if defined( HAVE_DEBUG_OUTPUT )
3687 if( libcnotify_verbose != 0 )
3688 {
3689 libcnotify_printf(
3690 "%s: B-tree sub node number\t: %" PRIu32 "\n",
3691 function,
3692 sub_node_number );
3693
3694 libcnotify_printf(
3695 "\n" );
3696 }
3697 #endif
3698 if( libfshfs_btree_file_get_node_by_number(
3699 btree_file,
3700 file_io_handle,
3701 sub_node_number,
3702 &sub_node,
3703 recursion_depth,
3704 error ) == -1 )
3705 {
3706 libcerror_error_set(
3707 error,
3708 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3709 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3710 "%s: unable to retrieve B-tree sub node: %" PRIu32 ".",
3711 function,
3712 sub_node_number );
3713
3714 goto on_error;
3715 }
3716 if( libfshfs_btree_node_get_node_type(
3717 sub_node,
3718 &node_type,
3719 error ) != 1 )
3720 {
3721 libcerror_error_set(
3722 error,
3723 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3724 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3725 "%s: unable to determine if B-tree sub node: %" PRIu32 " type.",
3726 function,
3727 sub_node_number );
3728
3729 goto on_error;
3730 }
3731 if( node_type == 0x00 )
3732 {
3733 result = libfshfs_catalog_btree_file_get_directory_entries_from_branch_node(
3734 btree_file,
3735 file_io_handle,
3736 sub_node,
3737 parent_identifier,
3738 directory_entries,
3739 recursion_depth + 1,
3740 error );
3741 }
3742 else if( node_type == 0xff )
3743 {
3744 result = libfshfs_catalog_btree_file_get_directory_entries_from_leaf_node(
3745 btree_file,
3746 sub_node,
3747 parent_identifier,
3748 directory_entries,
3749 error );
3750 }
3751 if( result != 1 )
3752 {
3753 libcerror_error_set(
3754 error,
3755 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3756 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3757 "%s: unable to retrieve directory entries from catalog B-tree node: %" PRIu32 ".",
3758 function,
3759 sub_node_number );
3760
3761 goto on_error;
3762 }
3763 if( node_key->parent_identifier > parent_identifier )
3764 {
3765 break;
3766 }
3767 }
3768 last_node_key = node_key;
3769 }
3770 return( 1 );
3771
3772 on_error:
3773 libcdata_array_empty(
3774 directory_entries,
3775 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_directory_entry_free,
3776 NULL );
3777
3778 return( -1 );
3779 }
3780
3781 /* Retrieves directory entries for a specific parent identifier from the catalog B-tree file
3782 * Returns 1 if successful or -1 on error
3783 */
libfshfs_catalog_btree_file_get_directory_entries(libfshfs_btree_file_t * btree_file,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,libcdata_array_t * directory_entries,libcerror_error_t ** error)3784 int libfshfs_catalog_btree_file_get_directory_entries(
3785 libfshfs_btree_file_t *btree_file,
3786 libbfio_handle_t *file_io_handle,
3787 uint32_t parent_identifier,
3788 libcdata_array_t *directory_entries,
3789 libcerror_error_t **error )
3790 {
3791 libfshfs_btree_node_t *root_node = NULL;
3792 static char *function = "libfshfs_catalog_btree_file_get_directory_entries";
3793 uint8_t node_type = 0;
3794 int result = 1;
3795
3796 if( libfshfs_btree_file_get_root_node(
3797 btree_file,
3798 file_io_handle,
3799 &root_node,
3800 0,
3801 error ) == -1 )
3802 {
3803 libcerror_error_set(
3804 error,
3805 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3806 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3807 "%s: unable to retrieve B-tree root node.",
3808 function );
3809
3810 goto on_error;
3811 }
3812 if( libfshfs_btree_node_get_node_type(
3813 root_node,
3814 &node_type,
3815 error ) != 1 )
3816 {
3817 libcerror_error_set(
3818 error,
3819 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3820 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3821 "%s: unable to determine if B-tree root node is a branch node.",
3822 function );
3823
3824 goto on_error;
3825 }
3826 if( node_type == 0x00 )
3827 {
3828 result = libfshfs_catalog_btree_file_get_directory_entries_from_branch_node(
3829 btree_file,
3830 file_io_handle,
3831 root_node,
3832 parent_identifier,
3833 directory_entries,
3834 1,
3835 error );
3836 }
3837 else if( node_type == 0xff )
3838 {
3839 result = libfshfs_catalog_btree_file_get_directory_entries_from_leaf_node(
3840 btree_file,
3841 root_node,
3842 parent_identifier,
3843 directory_entries,
3844 error );
3845 }
3846 if( result != 1 )
3847 {
3848 libcerror_error_set(
3849 error,
3850 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3851 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3852 "%s: unable to retrieve directory entries from catalog B-tree root node.",
3853 function );
3854
3855 goto on_error;
3856 }
3857 return( 1 );
3858
3859 on_error:
3860 libcdata_array_empty(
3861 directory_entries,
3862 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_directory_entry_free,
3863 NULL );
3864
3865 return( -1 );
3866 }
3867
3868