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