1 /*
2 * File system 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 <memory.h>
24 #include <narrow_string.h>
25 #include <types.h>
26
27 #include "libfshfs_attribute_record.h"
28 #include "libfshfs_attributes_btree_file.h"
29 #include "libfshfs_btree_file.h"
30 #include "libfshfs_catalog_btree_file.h"
31 #include "libfshfs_definitions.h"
32 #include "libfshfs_directory_entry.h"
33 #include "libfshfs_extent.h"
34 #include "libfshfs_extents_btree_file.h"
35 #include "libfshfs_file_system.h"
36 #include "libfshfs_fork_descriptor.h"
37 #include "libfshfs_libbfio.h"
38 #include "libfshfs_libcerror.h"
39 #include "libfshfs_libcthreads.h"
40
41 /* Creates a file system
42 * Make sure the value file_system is referencing, is set to NULL
43 * Returns 1 if successful or -1 on error
44 */
libfshfs_file_system_initialize(libfshfs_file_system_t ** file_system,uint8_t use_case_folding,libcerror_error_t ** error)45 int libfshfs_file_system_initialize(
46 libfshfs_file_system_t **file_system,
47 uint8_t use_case_folding,
48 libcerror_error_t **error )
49 {
50 static char *function = "libfshfs_file_system_initialize";
51
52 if( file_system == NULL )
53 {
54 libcerror_error_set(
55 error,
56 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58 "%s: invalid file system.",
59 function );
60
61 return( -1 );
62 }
63 if( *file_system != NULL )
64 {
65 libcerror_error_set(
66 error,
67 LIBCERROR_ERROR_DOMAIN_RUNTIME,
68 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69 "%s: invalid file system value already set.",
70 function );
71
72 return( -1 );
73 }
74 *file_system = memory_allocate_structure(
75 libfshfs_file_system_t );
76
77 if( *file_system == NULL )
78 {
79 libcerror_error_set(
80 error,
81 LIBCERROR_ERROR_DOMAIN_MEMORY,
82 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83 "%s: unable to create file system.",
84 function );
85
86 goto on_error;
87 }
88 if( memory_set(
89 *file_system,
90 0,
91 sizeof( libfshfs_file_system_t ) ) == NULL )
92 {
93 libcerror_error_set(
94 error,
95 LIBCERROR_ERROR_DOMAIN_MEMORY,
96 LIBCERROR_MEMORY_ERROR_SET_FAILED,
97 "%s: unable to clear file system.",
98 function );
99
100 memory_free(
101 *file_system );
102
103 *file_system = NULL;
104
105 return( -1 );
106 }
107 #if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
108 if( libcthreads_read_write_lock_initialize(
109 &( ( *file_system )->read_write_lock ),
110 error ) != 1 )
111 {
112 libcerror_error_set(
113 error,
114 LIBCERROR_ERROR_DOMAIN_RUNTIME,
115 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
116 "%s: unable to initialize read/write lock.",
117 function );
118
119 goto on_error;
120 }
121 #endif
122 ( *file_system )->use_case_folding = use_case_folding;
123
124 return( 1 );
125
126 on_error:
127 if( *file_system != NULL )
128 {
129 memory_free(
130 *file_system );
131
132 *file_system = NULL;
133 }
134 return( -1 );
135 }
136
137 /* Frees a file system
138 * Returns 1 if successful or -1 on error
139 */
libfshfs_file_system_free(libfshfs_file_system_t ** file_system,libcerror_error_t ** error)140 int libfshfs_file_system_free(
141 libfshfs_file_system_t **file_system,
142 libcerror_error_t **error )
143 {
144 static char *function = "libfshfs_file_system_free";
145 int result = 1;
146
147 if( file_system == NULL )
148 {
149 libcerror_error_set(
150 error,
151 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
152 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
153 "%s: invalid file system.",
154 function );
155
156 return( -1 );
157 }
158 if( *file_system != NULL )
159 {
160 #if defined( HAVE_LIBFSHFS_MULTI_THREAD_SUPPORT )
161 if( libcthreads_read_write_lock_free(
162 &( ( *file_system )->read_write_lock ),
163 error ) != 1 )
164 {
165 libcerror_error_set(
166 error,
167 LIBCERROR_ERROR_DOMAIN_RUNTIME,
168 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
169 "%s: unable to free read/write lock.",
170 function );
171
172 result = -1;
173 }
174 #endif
175 if( ( *file_system )->extents_btree_file != NULL )
176 {
177 if( libfshfs_btree_file_free(
178 &( ( *file_system )->extents_btree_file ),
179 error ) != 1 )
180 {
181 libcerror_error_set(
182 error,
183 LIBCERROR_ERROR_DOMAIN_RUNTIME,
184 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
185 "%s: unable to free extents B-tree file.",
186 function );
187
188 result = -1;
189 }
190 }
191 if( ( *file_system )->catalog_btree_file != NULL )
192 {
193 if( libfshfs_btree_file_free(
194 &( ( *file_system )->catalog_btree_file ),
195 error ) != 1 )
196 {
197 libcerror_error_set(
198 error,
199 LIBCERROR_ERROR_DOMAIN_RUNTIME,
200 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
201 "%s: unable to free catalog B-tree file.",
202 function );
203
204 result = -1;
205 }
206 }
207 if( ( *file_system )->attributes_btree_file != NULL )
208 {
209 if( libfshfs_btree_file_free(
210 &( ( *file_system )->attributes_btree_file ),
211 error ) != 1 )
212 {
213 libcerror_error_set(
214 error,
215 LIBCERROR_ERROR_DOMAIN_RUNTIME,
216 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
217 "%s: unable to free attributes B-tree file.",
218 function );
219
220 result = -1;
221 }
222 }
223 memory_free(
224 *file_system );
225
226 *file_system = NULL;
227 }
228 return( result );
229 }
230
231 /* Reads the attributes B-tree file
232 * Returns 1 if successful or -1 on error
233 */
libfshfs_file_system_read_attributes_file(libfshfs_file_system_t * file_system,libfshfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfshfs_fork_descriptor_t * fork_descriptor,libcerror_error_t ** error)234 int libfshfs_file_system_read_attributes_file(
235 libfshfs_file_system_t *file_system,
236 libfshfs_io_handle_t *io_handle,
237 libbfio_handle_t *file_io_handle,
238 libfshfs_fork_descriptor_t *fork_descriptor,
239 libcerror_error_t **error )
240 {
241 static char *function = "libfshfs_file_system_read_attributes_file";
242 int result = 0;
243
244 if( file_system == NULL )
245 {
246 libcerror_error_set(
247 error,
248 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
249 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
250 "%s: invalid file system.",
251 function );
252
253 return( -1 );
254 }
255 if( file_system->attributes_btree_file != NULL )
256 {
257 libcerror_error_set(
258 error,
259 LIBCERROR_ERROR_DOMAIN_RUNTIME,
260 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
261 "%s: invalid file system - attributes B-tree file value already set.",
262 function );
263
264 return( -1 );
265 }
266 if( fork_descriptor == NULL )
267 {
268 libcerror_error_set(
269 error,
270 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272 "%s: invalid fork descriptor.",
273 function );
274
275 return( -1 );
276 }
277 if( libfshfs_btree_file_initialize(
278 &( file_system->attributes_btree_file ),
279 error ) != 1 )
280 {
281 libcerror_error_set(
282 error,
283 LIBCERROR_ERROR_DOMAIN_RUNTIME,
284 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
285 "%s: unable to create attributes B-tree file.",
286 function );
287
288 goto on_error;
289 }
290 if( libfshfs_fork_descriptor_get_extents(
291 fork_descriptor,
292 file_system->attributes_btree_file->extents,
293 error ) != 1 )
294 {
295 libcerror_error_set(
296 error,
297 LIBCERROR_ERROR_DOMAIN_RUNTIME,
298 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
299 "%s: unable to retrieve extents of attributes B-tree file.",
300 function );
301
302 goto on_error;
303 }
304 result = libfshfs_fork_descriptor_has_extents_overflow(
305 fork_descriptor,
306 error );
307
308 if( result == -1 )
309 {
310 libcerror_error_set(
311 error,
312 LIBCERROR_ERROR_DOMAIN_RUNTIME,
313 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
314 "%s: unable to determine if fork descriptor has extents overflow.",
315 function );
316
317 goto on_error;
318 }
319 else if( result != 0 )
320 {
321 if( libfshfs_extents_btree_file_get_extents(
322 file_system->extents_btree_file,
323 file_io_handle,
324 LIBFSHFS_ATTRIBUTES_FILE_IDENTIFIER,
325 LIBFSHFS_FORK_TYPE_DATA,
326 file_system->attributes_btree_file->extents,
327 error ) != 1 )
328 {
329 libcerror_error_set(
330 error,
331 LIBCERROR_ERROR_DOMAIN_RUNTIME,
332 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
333 "%s: unable to retrieve extents for attributes B-tree file entry: %" PRIu32 " from extents (overflow) B-tree file.",
334 function,
335 LIBFSHFS_ATTRIBUTES_FILE_IDENTIFIER );
336
337 goto on_error;
338 }
339 }
340 file_system->attributes_btree_file->size = fork_descriptor->size;
341
342 if( libfshfs_btree_file_read_file_io_handle(
343 file_system->attributes_btree_file,
344 io_handle,
345 file_io_handle,
346 error ) != 1 )
347 {
348 libcerror_error_set(
349 error,
350 LIBCERROR_ERROR_DOMAIN_RUNTIME,
351 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
352 "%s: unable to read attributes B-tree file.",
353 function );
354
355 goto on_error;
356 }
357 return( 1 );
358
359 on_error:
360 if( file_system->attributes_btree_file != NULL )
361 {
362 libfshfs_btree_file_free(
363 &( file_system->attributes_btree_file ),
364 NULL );
365 }
366 return( -1 );
367 }
368
369 /* Reads the catalog B-tree file
370 * Returns 1 if successful or -1 on error
371 */
libfshfs_file_system_read_catalog_file(libfshfs_file_system_t * file_system,libfshfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfshfs_fork_descriptor_t * fork_descriptor,libcerror_error_t ** error)372 int libfshfs_file_system_read_catalog_file(
373 libfshfs_file_system_t *file_system,
374 libfshfs_io_handle_t *io_handle,
375 libbfio_handle_t *file_io_handle,
376 libfshfs_fork_descriptor_t *fork_descriptor,
377 libcerror_error_t **error )
378 {
379 static char *function = "libfshfs_file_system_read_catalog_file";
380 int result = 0;
381
382 if( file_system == NULL )
383 {
384 libcerror_error_set(
385 error,
386 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
387 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
388 "%s: invalid file system.",
389 function );
390
391 return( -1 );
392 }
393 if( file_system->catalog_btree_file != NULL )
394 {
395 libcerror_error_set(
396 error,
397 LIBCERROR_ERROR_DOMAIN_RUNTIME,
398 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
399 "%s: invalid file system - catalog B-tree file value already set.",
400 function );
401
402 return( -1 );
403 }
404 if( fork_descriptor == NULL )
405 {
406 libcerror_error_set(
407 error,
408 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
409 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
410 "%s: invalid fork descriptor.",
411 function );
412
413 return( -1 );
414 }
415 if( libfshfs_btree_file_initialize(
416 &( file_system->catalog_btree_file ),
417 error ) != 1 )
418 {
419 libcerror_error_set(
420 error,
421 LIBCERROR_ERROR_DOMAIN_RUNTIME,
422 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
423 "%s: unable to create catalog B-tree file.",
424 function );
425
426 goto on_error;
427 }
428 if( libfshfs_fork_descriptor_get_extents(
429 fork_descriptor,
430 file_system->catalog_btree_file->extents,
431 error ) != 1 )
432 {
433 libcerror_error_set(
434 error,
435 LIBCERROR_ERROR_DOMAIN_RUNTIME,
436 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
437 "%s: unable to retrieve extents of catalog B-tree file.",
438 function );
439
440 goto on_error;
441 }
442 result = libfshfs_fork_descriptor_has_extents_overflow(
443 fork_descriptor,
444 error );
445
446 if( result == -1 )
447 {
448 libcerror_error_set(
449 error,
450 LIBCERROR_ERROR_DOMAIN_RUNTIME,
451 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
452 "%s: unable to determine if fork descriptor has extents overflow.",
453 function );
454
455 goto on_error;
456 }
457 else if( result != 0 )
458 {
459 if( libfshfs_extents_btree_file_get_extents(
460 file_system->extents_btree_file,
461 file_io_handle,
462 LIBFSHFS_CATALOG_FILE_IDENTIFIER,
463 LIBFSHFS_FORK_TYPE_DATA,
464 file_system->catalog_btree_file->extents,
465 error ) != 1 )
466 {
467 libcerror_error_set(
468 error,
469 LIBCERROR_ERROR_DOMAIN_RUNTIME,
470 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
471 "%s: unable to retrieve extents for catalog B-tree file entry: %" PRIu32 " from extents (overflow) B-tree file.",
472 function,
473 LIBFSHFS_CATALOG_FILE_IDENTIFIER );
474
475 goto on_error;
476 }
477 }
478 file_system->catalog_btree_file->size = fork_descriptor->size;
479
480 if( libfshfs_btree_file_read_file_io_handle(
481 file_system->catalog_btree_file,
482 io_handle,
483 file_io_handle,
484 error ) != 1 )
485 {
486 libcerror_error_set(
487 error,
488 LIBCERROR_ERROR_DOMAIN_RUNTIME,
489 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
490 "%s: unable to read catalog B-tree file.",
491 function );
492
493 goto on_error;
494 }
495 return( 1 );
496
497 on_error:
498 if( file_system->catalog_btree_file != NULL )
499 {
500 libfshfs_btree_file_free(
501 &( file_system->catalog_btree_file ),
502 NULL );
503 }
504 return( -1 );
505 }
506
507 /* Reads the extents B-tree file
508 * Returns 1 if successful or -1 on error
509 */
libfshfs_file_system_read_extents_file(libfshfs_file_system_t * file_system,libfshfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfshfs_fork_descriptor_t * fork_descriptor,libcerror_error_t ** error)510 int libfshfs_file_system_read_extents_file(
511 libfshfs_file_system_t *file_system,
512 libfshfs_io_handle_t *io_handle,
513 libbfio_handle_t *file_io_handle,
514 libfshfs_fork_descriptor_t *fork_descriptor,
515 libcerror_error_t **error )
516 {
517 static char *function = "libfshfs_file_system_read_extents_file";
518 int result = 0;
519
520 if( file_system == NULL )
521 {
522 libcerror_error_set(
523 error,
524 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
525 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
526 "%s: invalid file system.",
527 function );
528
529 return( -1 );
530 }
531 if( file_system->extents_btree_file != NULL )
532 {
533 libcerror_error_set(
534 error,
535 LIBCERROR_ERROR_DOMAIN_RUNTIME,
536 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
537 "%s: invalid file system - extents B-tree file value already set.",
538 function );
539
540 return( -1 );
541 }
542 if( fork_descriptor == NULL )
543 {
544 libcerror_error_set(
545 error,
546 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
547 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
548 "%s: invalid fork descriptor.",
549 function );
550
551 return( -1 );
552 }
553 result = libfshfs_fork_descriptor_has_extents_overflow(
554 fork_descriptor,
555 error );
556
557 if( result == -1 )
558 {
559 libcerror_error_set(
560 error,
561 LIBCERROR_ERROR_DOMAIN_RUNTIME,
562 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
563 "%s: unable to determine if fork descriptor has extents overflow.",
564 function );
565
566 goto on_error;
567 }
568 else if( result != 0 )
569 {
570 libcerror_error_set(
571 error,
572 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
573 LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
574 "%s: unsupported fork descriptor has extents overflow.",
575 function );
576
577 goto on_error;
578 }
579 if( libfshfs_btree_file_initialize(
580 &( file_system->extents_btree_file ),
581 error ) != 1 )
582 {
583 libcerror_error_set(
584 error,
585 LIBCERROR_ERROR_DOMAIN_RUNTIME,
586 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
587 "%s: unable to create extents B-tree file.",
588 function );
589
590 goto on_error;
591 }
592 if( libfshfs_fork_descriptor_get_extents(
593 fork_descriptor,
594 file_system->extents_btree_file->extents,
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 extents of extents B-tree file.",
602 function );
603
604 goto on_error;
605 }
606 file_system->extents_btree_file->size = fork_descriptor->size;
607
608 if( libfshfs_btree_file_read_file_io_handle(
609 file_system->extents_btree_file,
610 io_handle,
611 file_io_handle,
612 error ) != 1 )
613 {
614 libcerror_error_set(
615 error,
616 LIBCERROR_ERROR_DOMAIN_RUNTIME,
617 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
618 "%s: unable to read extents B-tree file.",
619 function );
620
621 goto on_error;
622 }
623 return( 1 );
624
625 on_error:
626 if( file_system->extents_btree_file != NULL )
627 {
628 libfshfs_btree_file_free(
629 &( file_system->extents_btree_file ),
630 NULL );
631 }
632 return( -1 );
633 }
634
635 /* Resolves an indirect node directory entry if available
636 * Returns 1 if successful or -1 on error
637 */
libfshfs_file_system_resolve_indirect_node_directory_entry(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,libfshfs_directory_entry_t * directory_entry,libcerror_error_t ** error)638 int libfshfs_file_system_resolve_indirect_node_directory_entry(
639 libfshfs_file_system_t *file_system,
640 libbfio_handle_t *file_io_handle,
641 libfshfs_directory_entry_t *directory_entry,
642 libcerror_error_t **error )
643 {
644 char indirect_node_path[ 64 ];
645
646 libfshfs_directory_entry_t *link_directory_entry = NULL;
647 intptr_t *catalog_record = NULL;
648 static char *function = "libfshfs_file_system_resolve_indirect_node_directory_entry";
649 size_t indirect_node_path_length = 0;
650 ssize_t print_count = 0;
651 uint32_t link_reference = 0;
652 int result = 0;
653
654 if( file_system == NULL )
655 {
656 libcerror_error_set(
657 error,
658 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660 "%s: invalid file system.",
661 function );
662
663 return( -1 );
664 }
665 if( directory_entry == NULL )
666 {
667 libcerror_error_set(
668 error,
669 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
670 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
671 "%s: invalid directory entry.",
672 function );
673
674 return( -1 );
675 }
676 result = libfshfs_directory_entry_get_link_reference(
677 directory_entry,
678 &link_reference,
679 error );
680
681 if( result == -1 )
682 {
683 libcerror_error_set(
684 error,
685 LIBCERROR_ERROR_DOMAIN_RUNTIME,
686 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
687 "%s: unable to retrieve link reference.",
688 function );
689
690 goto on_error;
691 }
692 else if( ( result != 0 )
693 && ( link_reference > 2 ) )
694 {
695 print_count = narrow_string_snprintf(
696 indirect_node_path,
697 64,
698 "/\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data/iNode%" PRIu32 "",
699 link_reference );
700
701 if( ( print_count <= -1 )
702 || ( print_count > 64 ) )
703 {
704 libcerror_error_set(
705 error,
706 LIBCERROR_ERROR_DOMAIN_RUNTIME,
707 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
708 "%s: unable to set indirect node path.",
709 function );
710
711 goto on_error;
712 }
713 indirect_node_path_length = narrow_string_length(
714 indirect_node_path );
715
716 result = libfshfs_catalog_btree_file_get_directory_entry_by_utf8_path(
717 file_system->catalog_btree_file,
718 file_io_handle,
719 (uint8_t *) indirect_node_path,
720 indirect_node_path_length,
721 file_system->use_case_folding,
722 &link_directory_entry,
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 indirect node: %" PRIu32 " directory entry by UTF-8 path.",
732 function,
733 link_reference );
734
735 goto on_error;
736 }
737 if( libfshfs_directory_entry_get_identifier(
738 directory_entry,
739 &( directory_entry->link_identifier ),
740 error ) != 1 )
741 {
742 libcerror_error_set(
743 error,
744 LIBCERROR_ERROR_DOMAIN_RUNTIME,
745 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
746 "%s: unable to retrieve directory entry identifier.",
747 function );
748
749 goto on_error;
750 }
751 catalog_record = directory_entry->catalog_record;
752 directory_entry->catalog_record = link_directory_entry->catalog_record;
753 link_directory_entry->catalog_record = catalog_record;
754
755 if( libfshfs_directory_entry_free(
756 &link_directory_entry,
757 error ) != 1 )
758 {
759 libcerror_error_set(
760 error,
761 LIBCERROR_ERROR_DOMAIN_RUNTIME,
762 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
763 "%s: unable to free directory entry.",
764 function );
765
766 goto on_error;
767 }
768 }
769 return( 1 );
770
771 on_error:
772 if( link_directory_entry != NULL )
773 {
774 libfshfs_directory_entry_free(
775 &link_directory_entry,
776 NULL );
777 }
778 return( -1 );
779 }
780
781 /* Retrieves a directory entry for a specific identifier
782 * Returns 1 if successful, 0 if not found or -1 on error
783 */
libfshfs_file_system_get_directory_entry_by_identifier(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t identifier,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)784 int libfshfs_file_system_get_directory_entry_by_identifier(
785 libfshfs_file_system_t *file_system,
786 libbfio_handle_t *file_io_handle,
787 uint32_t identifier,
788 libfshfs_directory_entry_t **directory_entry,
789 libcerror_error_t **error )
790 {
791 static char *function = "libfshfs_file_system_get_directory_entry_by_identifier";
792 int result = 0;
793
794 if( file_system == NULL )
795 {
796 libcerror_error_set(
797 error,
798 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
799 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
800 "%s: invalid file system.",
801 function );
802
803 return( -1 );
804 }
805 result = libfshfs_catalog_btree_file_get_directory_entry_by_identifier(
806 file_system->catalog_btree_file,
807 file_io_handle,
808 identifier,
809 directory_entry,
810 error );
811
812 if( result == -1 )
813 {
814 libcerror_error_set(
815 error,
816 LIBCERROR_ERROR_DOMAIN_RUNTIME,
817 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
818 "%s: unable to retrieve directory entry: %" PRIu32 ".",
819 function,
820 identifier );
821
822 return( -1 );
823 }
824 return( result );
825 }
826
827 /* Retrieves a directory entry for an UTF-8 encoded name
828 * Returns 1 if successful, 0 if not found or -1 on error
829 */
libfshfs_file_system_get_directory_entry_by_utf8_name(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,const uint8_t * utf8_string,size_t utf8_string_length,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)830 int libfshfs_file_system_get_directory_entry_by_utf8_name(
831 libfshfs_file_system_t *file_system,
832 libbfio_handle_t *file_io_handle,
833 uint32_t parent_identifier,
834 const uint8_t *utf8_string,
835 size_t utf8_string_length,
836 libfshfs_directory_entry_t **directory_entry,
837 libcerror_error_t **error )
838 {
839 libfshfs_directory_entry_t *safe_directory_entry = NULL;
840 static char *function = "libfshfs_file_system_get_directory_entry_by_utf8_name";
841 int result = 0;
842
843 if( file_system == NULL )
844 {
845 libcerror_error_set(
846 error,
847 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
848 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
849 "%s: invalid file system.",
850 function );
851
852 return( -1 );
853 }
854 if( directory_entry == NULL )
855 {
856 libcerror_error_set(
857 error,
858 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
859 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
860 "%s: invalid directory entry.",
861 function );
862
863 return( -1 );
864 }
865 result = libfshfs_catalog_btree_file_get_directory_entry_by_utf8_name(
866 file_system->catalog_btree_file,
867 file_io_handle,
868 parent_identifier,
869 utf8_string,
870 utf8_string_length,
871 file_system->use_case_folding,
872 &safe_directory_entry,
873 error );
874
875 if( result == -1 )
876 {
877 libcerror_error_set(
878 error,
879 LIBCERROR_ERROR_DOMAIN_RUNTIME,
880 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
881 "%s: unable to retrieve directory entry by UTF-8 name.",
882 function );
883
884 goto on_error;
885 }
886 else if( result != 0 )
887 {
888 if( libfshfs_file_system_resolve_indirect_node_directory_entry(
889 file_system,
890 file_io_handle,
891 safe_directory_entry,
892 error ) != 1 )
893 {
894 libcerror_error_set(
895 error,
896 LIBCERROR_ERROR_DOMAIN_RUNTIME,
897 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
898 "%s: unable to resolve indirect node directory entry.",
899 function );
900
901 goto on_error;
902 }
903 *directory_entry = safe_directory_entry;
904 }
905 return( result );
906
907 on_error:
908 if( safe_directory_entry != NULL )
909 {
910 libfshfs_directory_entry_free(
911 &safe_directory_entry,
912 NULL );
913 }
914 return( -1 );
915 }
916
917 /* Retrieves a directory entry for a specific identifier
918 * Returns 1 if successful, 0 if not found or -1 on error
919 */
libfshfs_file_system_get_directory_entry_by_utf8_path(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,const uint8_t * utf8_string,size_t utf8_string_length,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)920 int libfshfs_file_system_get_directory_entry_by_utf8_path(
921 libfshfs_file_system_t *file_system,
922 libbfio_handle_t *file_io_handle,
923 const uint8_t *utf8_string,
924 size_t utf8_string_length,
925 libfshfs_directory_entry_t **directory_entry,
926 libcerror_error_t **error )
927 {
928 libfshfs_directory_entry_t *safe_directory_entry = NULL;
929 static char *function = "libfshfs_file_system_get_directory_entry_by_utf8_path";
930 int result = 0;
931
932 if( file_system == NULL )
933 {
934 libcerror_error_set(
935 error,
936 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
937 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
938 "%s: invalid file system.",
939 function );
940
941 return( -1 );
942 }
943 if( directory_entry == NULL )
944 {
945 libcerror_error_set(
946 error,
947 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
948 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
949 "%s: invalid directory entry.",
950 function );
951
952 return( -1 );
953 }
954 result = libfshfs_catalog_btree_file_get_directory_entry_by_utf8_path(
955 file_system->catalog_btree_file,
956 file_io_handle,
957 utf8_string,
958 utf8_string_length,
959 file_system->use_case_folding,
960 &safe_directory_entry,
961 error );
962
963 if( result == -1 )
964 {
965 libcerror_error_set(
966 error,
967 LIBCERROR_ERROR_DOMAIN_RUNTIME,
968 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
969 "%s: unable to retrieve directory entry by UTF-8 path.",
970 function );
971
972 goto on_error;
973 }
974 else if( result != 0 )
975 {
976 if( libfshfs_file_system_resolve_indirect_node_directory_entry(
977 file_system,
978 file_io_handle,
979 safe_directory_entry,
980 error ) != 1 )
981 {
982 libcerror_error_set(
983 error,
984 LIBCERROR_ERROR_DOMAIN_RUNTIME,
985 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
986 "%s: unable to resolve indirect node directory entry.",
987 function );
988
989 goto on_error;
990 }
991 *directory_entry = safe_directory_entry;
992 }
993 return( result );
994
995 on_error:
996 if( safe_directory_entry != NULL )
997 {
998 libfshfs_directory_entry_free(
999 &safe_directory_entry,
1000 NULL );
1001 }
1002 return( -1 );
1003 }
1004
1005 /* Retrieves a directory entry for an UTF-16 encoded name
1006 * Returns 1 if successful, 0 if not found or -1 on error
1007 */
libfshfs_file_system_get_directory_entry_by_utf16_name(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,const uint16_t * utf16_string,size_t utf16_string_length,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)1008 int libfshfs_file_system_get_directory_entry_by_utf16_name(
1009 libfshfs_file_system_t *file_system,
1010 libbfio_handle_t *file_io_handle,
1011 uint32_t parent_identifier,
1012 const uint16_t *utf16_string,
1013 size_t utf16_string_length,
1014 libfshfs_directory_entry_t **directory_entry,
1015 libcerror_error_t **error )
1016 {
1017 libfshfs_directory_entry_t *safe_directory_entry = NULL;
1018 static char *function = "libfshfs_file_system_get_directory_entry_by_utf16_name";
1019 int result = 0;
1020
1021 if( file_system == NULL )
1022 {
1023 libcerror_error_set(
1024 error,
1025 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1026 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1027 "%s: invalid file system.",
1028 function );
1029
1030 return( -1 );
1031 }
1032 if( directory_entry == NULL )
1033 {
1034 libcerror_error_set(
1035 error,
1036 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1037 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1038 "%s: invalid directory entry.",
1039 function );
1040
1041 return( -1 );
1042 }
1043 result = libfshfs_catalog_btree_file_get_directory_entry_by_utf16_name(
1044 file_system->catalog_btree_file,
1045 file_io_handle,
1046 parent_identifier,
1047 utf16_string,
1048 utf16_string_length,
1049 file_system->use_case_folding,
1050 &safe_directory_entry,
1051 error );
1052
1053 if( result == -1 )
1054 {
1055 libcerror_error_set(
1056 error,
1057 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1058 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1059 "%s: unable to retrieve directory entry by UTF-16 name.",
1060 function );
1061
1062 goto on_error;
1063 }
1064 else if( result != 0 )
1065 {
1066 if( libfshfs_file_system_resolve_indirect_node_directory_entry(
1067 file_system,
1068 file_io_handle,
1069 safe_directory_entry,
1070 error ) != 1 )
1071 {
1072 libcerror_error_set(
1073 error,
1074 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1075 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1076 "%s: unable to resolve indirect node directory entry.",
1077 function );
1078
1079 goto on_error;
1080 }
1081 *directory_entry = safe_directory_entry;
1082 }
1083 return( result );
1084
1085 on_error:
1086 if( safe_directory_entry != NULL )
1087 {
1088 libfshfs_directory_entry_free(
1089 &safe_directory_entry,
1090 NULL );
1091 }
1092 return( -1 );
1093 }
1094
1095 /* Retrieves a directory entry for a specific identifier
1096 * Returns 1 if successful, 0 if not found or -1 on error
1097 */
libfshfs_file_system_get_directory_entry_by_utf16_path(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,const uint16_t * utf16_string,size_t utf16_string_length,libfshfs_directory_entry_t ** directory_entry,libcerror_error_t ** error)1098 int libfshfs_file_system_get_directory_entry_by_utf16_path(
1099 libfshfs_file_system_t *file_system,
1100 libbfio_handle_t *file_io_handle,
1101 const uint16_t *utf16_string,
1102 size_t utf16_string_length,
1103 libfshfs_directory_entry_t **directory_entry,
1104 libcerror_error_t **error )
1105 {
1106 libfshfs_directory_entry_t *safe_directory_entry = NULL;
1107 static char *function = "libfshfs_file_system_get_directory_entry_by_utf16_path";
1108 int result = 0;
1109
1110 if( file_system == NULL )
1111 {
1112 libcerror_error_set(
1113 error,
1114 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1115 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1116 "%s: invalid file system.",
1117 function );
1118
1119 return( -1 );
1120 }
1121 if( directory_entry == NULL )
1122 {
1123 libcerror_error_set(
1124 error,
1125 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1126 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1127 "%s: invalid directory entry.",
1128 function );
1129
1130 return( -1 );
1131 }
1132 result = libfshfs_catalog_btree_file_get_directory_entry_by_utf16_path(
1133 file_system->catalog_btree_file,
1134 file_io_handle,
1135 utf16_string,
1136 utf16_string_length,
1137 file_system->use_case_folding,
1138 &safe_directory_entry,
1139 error );
1140
1141 if( result == -1 )
1142 {
1143 libcerror_error_set(
1144 error,
1145 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1146 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1147 "%s: unable to retrieve directory entry by UTF-16 path.",
1148 function );
1149
1150 goto on_error;
1151 }
1152 else if( result != 0 )
1153 {
1154 if( libfshfs_file_system_resolve_indirect_node_directory_entry(
1155 file_system,
1156 file_io_handle,
1157 safe_directory_entry,
1158 error ) != 1 )
1159 {
1160 libcerror_error_set(
1161 error,
1162 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1163 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1164 "%s: unable to resolve indirect node directory entry.",
1165 function );
1166
1167 goto on_error;
1168 }
1169 *directory_entry = safe_directory_entry;
1170 }
1171 return( result );
1172
1173 on_error:
1174 if( safe_directory_entry != NULL )
1175 {
1176 libfshfs_directory_entry_free(
1177 &safe_directory_entry,
1178 NULL );
1179 }
1180 return( -1 );
1181 }
1182
1183 /* Retrieves directory entries for a specific parent identifier
1184 * Returns 1 if successful or -1 on error
1185 */
libfshfs_file_system_get_directory_entries(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,libcdata_array_t ** directory_entries,libcerror_error_t ** error)1186 int libfshfs_file_system_get_directory_entries(
1187 libfshfs_file_system_t *file_system,
1188 libbfio_handle_t *file_io_handle,
1189 uint32_t parent_identifier,
1190 libcdata_array_t **directory_entries,
1191 libcerror_error_t **error )
1192 {
1193 static char *function = "libfshfs_file_system_get_directory_entries";
1194
1195 if( file_system == NULL )
1196 {
1197 libcerror_error_set(
1198 error,
1199 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1200 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1201 "%s: invalid file system.",
1202 function );
1203
1204 return( -1 );
1205 }
1206 if( directory_entries == NULL )
1207 {
1208 libcerror_error_set(
1209 error,
1210 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1211 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1212 "%s: invalid directory entries.",
1213 function );
1214
1215 return( -1 );
1216 }
1217 if( libcdata_array_initialize(
1218 directory_entries,
1219 0,
1220 error ) != 1 )
1221 {
1222 libcerror_error_set(
1223 error,
1224 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1225 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1226 "%s: unable to create directory entries array.",
1227 function );
1228
1229 goto on_error;
1230 }
1231 if( libfshfs_catalog_btree_file_get_directory_entries(
1232 file_system->catalog_btree_file,
1233 file_io_handle,
1234 parent_identifier,
1235 *directory_entries,
1236 error ) != 1 )
1237 {
1238 libcerror_error_set(
1239 error,
1240 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1241 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1242 "%s: unable to retrieve directory entries for entry: %" PRIu32 " from catalog B-tree file.",
1243 function,
1244 parent_identifier );
1245
1246 goto on_error;
1247 }
1248 return( 1 );
1249
1250 on_error:
1251 if( *directory_entries != NULL )
1252 {
1253 libcdata_array_free(
1254 directory_entries,
1255 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_directory_entry_free,
1256 NULL );
1257 }
1258 return( -1 );
1259 }
1260
1261 /* Retrieves extents for a specific fork descriptor
1262 * Returns 1 if successful or -1 on error
1263 */
libfshfs_file_system_get_extents(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t identifier,uint8_t fork_type,libfshfs_fork_descriptor_t * fork_descriptor,libcdata_array_t ** extents,libcerror_error_t ** error)1264 int libfshfs_file_system_get_extents(
1265 libfshfs_file_system_t *file_system,
1266 libbfio_handle_t *file_io_handle,
1267 uint32_t identifier,
1268 uint8_t fork_type,
1269 libfshfs_fork_descriptor_t *fork_descriptor,
1270 libcdata_array_t **extents,
1271 libcerror_error_t **error )
1272 {
1273 static char *function = "libfshfs_file_system_get_extents";
1274 int result = 0;
1275
1276 if( file_system == NULL )
1277 {
1278 libcerror_error_set(
1279 error,
1280 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1281 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1282 "%s: invalid file system.",
1283 function );
1284
1285 return( -1 );
1286 }
1287 if( extents == NULL )
1288 {
1289 libcerror_error_set(
1290 error,
1291 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1292 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1293 "%s: invalid extents.",
1294 function );
1295
1296 return( -1 );
1297 }
1298 if( libcdata_array_initialize(
1299 extents,
1300 0,
1301 error ) != 1 )
1302 {
1303 libcerror_error_set(
1304 error,
1305 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1306 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1307 "%s: unable to create extents array.",
1308 function );
1309
1310 goto on_error;
1311 }
1312 if( libfshfs_fork_descriptor_get_extents(
1313 fork_descriptor,
1314 *extents,
1315 error ) != 1 )
1316 {
1317 libcerror_error_set(
1318 error,
1319 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1320 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1321 "%s: unable to retrieve extents for entry: %" PRIu32 " from fork descriptor.",
1322 function,
1323 identifier );
1324
1325 goto on_error;
1326 }
1327 result = libfshfs_fork_descriptor_has_extents_overflow(
1328 fork_descriptor,
1329 error );
1330
1331 if( result == -1 )
1332 {
1333 libcerror_error_set(
1334 error,
1335 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1336 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1337 "%s: unable to determine if fork descriptor has extents overflow.",
1338 function );
1339
1340 goto on_error;
1341 }
1342 else if( result != 0 )
1343 {
1344 if( libfshfs_extents_btree_file_get_extents(
1345 file_system->extents_btree_file,
1346 file_io_handle,
1347 identifier,
1348 fork_type,
1349 *extents,
1350 error ) != 1 )
1351 {
1352 libcerror_error_set(
1353 error,
1354 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1355 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1356 "%s: unable to retrieve extents for entry: %" PRIu32 " from extents (overflow) B-tree file.",
1357 function,
1358 identifier );
1359
1360 goto on_error;
1361 }
1362 }
1363 return( 1 );
1364
1365 on_error:
1366 if( *extents != NULL )
1367 {
1368 libcdata_array_free(
1369 extents,
1370 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_extent_free,
1371 NULL );
1372 }
1373 return( -1 );
1374 }
1375
1376 /* Retrieves attributes for a specific parent identifier
1377 * Returns 1 if successful or -1 on error
1378 */
libfshfs_file_system_get_attributes(libfshfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t parent_identifier,libcdata_array_t ** attributes,libcerror_error_t ** error)1379 int libfshfs_file_system_get_attributes(
1380 libfshfs_file_system_t *file_system,
1381 libbfio_handle_t *file_io_handle,
1382 uint32_t parent_identifier,
1383 libcdata_array_t **attributes,
1384 libcerror_error_t **error )
1385 {
1386 static char *function = "libfshfs_file_system_get_attributes";
1387
1388 if( file_system == NULL )
1389 {
1390 libcerror_error_set(
1391 error,
1392 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1393 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1394 "%s: invalid file system.",
1395 function );
1396
1397 return( -1 );
1398 }
1399 if( attributes == NULL )
1400 {
1401 libcerror_error_set(
1402 error,
1403 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1404 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1405 "%s: invalid attributes.",
1406 function );
1407
1408 return( -1 );
1409 }
1410 if( libcdata_array_initialize(
1411 attributes,
1412 0,
1413 error ) != 1 )
1414 {
1415 libcerror_error_set(
1416 error,
1417 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1418 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1419 "%s: unable to create attributes array.",
1420 function );
1421
1422 goto on_error;
1423 }
1424 if( libfshfs_attributes_btree_file_get_attributes(
1425 file_system->attributes_btree_file,
1426 file_io_handle,
1427 parent_identifier,
1428 *attributes,
1429 error ) != 1 )
1430 {
1431 libcerror_error_set(
1432 error,
1433 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1434 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1435 "%s: unable to retrieve attributes for entry: %" PRIu32 " from attributes B-tree file.",
1436 function,
1437 parent_identifier );
1438
1439 goto on_error;
1440 }
1441 return( 1 );
1442
1443 on_error:
1444 if( *attributes != NULL )
1445 {
1446 libcdata_array_free(
1447 attributes,
1448 (int (*)(intptr_t **, libcerror_error_t **)) &libfshfs_attribute_record_free,
1449 NULL );
1450 }
1451 return( -1 );
1452 }
1453
1454