1 /*
2  * File entry functions
3  *
4  * Copyright (C) 2018-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 <types.h>
25 
26 #include "libfsapfs_compressed_data_header.h"
27 #include "libfsapfs_data_stream.h"
28 #include "libfsapfs_definitions.h"
29 #include "libfsapfs_directory_record.h"
30 #include "libfsapfs_encryption_context.h"
31 #include "libfsapfs_extended_attribute.h"
32 #include "libfsapfs_file_entry.h"
33 #include "libfsapfs_file_extent.h"
34 #include "libfsapfs_file_system_btree.h"
35 #include "libfsapfs_inode.h"
36 #include "libfsapfs_io_handle.h"
37 #include "libfsapfs_libbfio.h"
38 #include "libfsapfs_libcdata.h"
39 #include "libfsapfs_libcerror.h"
40 #include "libfsapfs_libcnotify.h"
41 #include "libfsapfs_libcthreads.h"
42 #include "libfsapfs_libfdata.h"
43 #include "libfsapfs_libuna.h"
44 #include "libfsapfs_types.h"
45 
46 #include "fsapfs_file_system.h"
47 
48 /* Creates a file entry
49  * Make sure the value file_entry is referencing, is set to NULL
50  * Returns 1 if successful or -1 on error
51  */
libfsapfs_file_entry_initialize(libfsapfs_file_entry_t ** file_entry,libfsapfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfsapfs_encryption_context_t * encryption_context,libfsapfs_file_system_btree_t * file_system_btree,libfsapfs_inode_t * inode,libfsapfs_directory_record_t * directory_record,libcerror_error_t ** error)52 int libfsapfs_file_entry_initialize(
53      libfsapfs_file_entry_t **file_entry,
54      libfsapfs_io_handle_t *io_handle,
55      libbfio_handle_t *file_io_handle,
56      libfsapfs_encryption_context_t *encryption_context,
57      libfsapfs_file_system_btree_t *file_system_btree,
58      libfsapfs_inode_t *inode,
59      libfsapfs_directory_record_t *directory_record,
60      libcerror_error_t **error )
61 {
62 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
63 	static char *function                                = "libfsapfs_file_entry_initialize";
64 
65 	if( file_entry == NULL )
66 	{
67 		libcerror_error_set(
68 		 error,
69 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
70 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
71 		 "%s: invalid file entry.",
72 		 function );
73 
74 		return( -1 );
75 	}
76 	if( *file_entry != NULL )
77 	{
78 		libcerror_error_set(
79 		 error,
80 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
81 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
82 		 "%s: invalid file entry value already set.",
83 		 function );
84 
85 		return( -1 );
86 	}
87 	internal_file_entry = memory_allocate_structure(
88 	                       libfsapfs_internal_file_entry_t );
89 
90 	if( internal_file_entry == NULL )
91 	{
92 		libcerror_error_set(
93 		 error,
94 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
95 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
96 		 "%s: unable to create file entry.",
97 		 function );
98 
99 		goto on_error;
100 	}
101 	if( memory_set(
102 	     internal_file_entry,
103 	     0,
104 	     sizeof( libfsapfs_internal_file_entry_t ) ) == NULL )
105 	{
106 		libcerror_error_set(
107 		 error,
108 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
109 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
110 		 "%s: unable to clear file entry.",
111 		 function );
112 
113 		memory_free(
114 		 internal_file_entry );
115 
116 		return( -1 );
117 	}
118 	internal_file_entry->io_handle          = io_handle;
119 	internal_file_entry->file_io_handle     = file_io_handle;
120 	internal_file_entry->encryption_context = encryption_context;
121 	internal_file_entry->file_system_btree  = file_system_btree;
122 	internal_file_entry->inode              = inode;
123 	internal_file_entry->directory_record   = directory_record;
124 	internal_file_entry->data_size          = (size64_t) -1;
125 
126 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
127 	if( libcthreads_read_write_lock_initialize(
128 	     &( internal_file_entry->read_write_lock ),
129 	     error ) != 1 )
130 	{
131 		libcerror_error_set(
132 		 error,
133 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
134 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
135 		 "%s: unable to initialize read/write lock.",
136 		 function );
137 
138 		goto on_error;
139 	}
140 #endif
141 	*file_entry = (libfsapfs_file_entry_t *) internal_file_entry;
142 
143 	return( 1 );
144 
145 on_error:
146 	if( internal_file_entry != NULL )
147 	{
148 		memory_free(
149 		 internal_file_entry );
150 	}
151 	return( -1 );
152 }
153 
154 /* Frees a file entry
155  * Returns 1 if successful or -1 on error
156  */
libfsapfs_file_entry_free(libfsapfs_file_entry_t ** file_entry,libcerror_error_t ** error)157 int libfsapfs_file_entry_free(
158      libfsapfs_file_entry_t **file_entry,
159      libcerror_error_t **error )
160 {
161 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
162 	static char *function                                = "libfsapfs_file_entry_free";
163 	int result                                           = 1;
164 
165 	if( file_entry == NULL )
166 	{
167 		libcerror_error_set(
168 		 error,
169 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
171 		 "%s: invalid file entry.",
172 		 function );
173 
174 		return( -1 );
175 	}
176 	if( *file_entry != NULL )
177 	{
178 		internal_file_entry = (libfsapfs_internal_file_entry_t *) *file_entry;
179 		*file_entry         = NULL;
180 
181 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
182 		if( libcthreads_read_write_lock_free(
183 		     &( internal_file_entry->read_write_lock ),
184 		     error ) != 1 )
185 		{
186 			libcerror_error_set(
187 			 error,
188 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
189 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
190 			 "%s: unable to free read/write lock.",
191 			 function );
192 
193 			result = -1;
194 		}
195 #endif
196 		/* The file_io_handle and file_system_btree references are freed elsewhere
197 		 */
198 		if( internal_file_entry->inode != NULL )
199 		{
200 			if( libfsapfs_inode_free(
201 			     &( internal_file_entry->inode ),
202 			     error ) != 1 )
203 			{
204 				libcerror_error_set(
205 				 error,
206 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
207 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
208 				 "%s: unable to free inode.",
209 				 function );
210 
211 				result = -1;
212 			}
213 		}
214 		if( internal_file_entry->directory_record != NULL )
215 		{
216 			if( libfsapfs_directory_record_free(
217 			     &( internal_file_entry->directory_record ),
218 			     error ) != 1 )
219 			{
220 				libcerror_error_set(
221 				 error,
222 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
223 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
224 				 "%s: unable to free directory record.",
225 				 function );
226 
227 				result = -1;
228 			}
229 		}
230 		if( internal_file_entry->extended_attributes != NULL )
231 		{
232 			if( libcdata_array_free(
233 			     &( internal_file_entry->extended_attributes ),
234 			     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_internal_extended_attribute_free,
235 			     error ) != 1 )
236 			{
237 				libcerror_error_set(
238 				 error,
239 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
240 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
241 				 "%s: unable to free extended attributes array.",
242 				 function );
243 
244 				result = -1;
245 			}
246 		}
247 		if( internal_file_entry->compressed_data_header != NULL )
248 		{
249 			if( libfsapfs_compressed_data_header_free(
250 			     &( internal_file_entry->compressed_data_header ),
251 			     error ) != 1 )
252 			{
253 				libcerror_error_set(
254 				 error,
255 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
256 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
257 				 "%s: unable to free compressed data header.",
258 				 function );
259 
260 				result = -1;
261 			}
262 		}
263 		if( internal_file_entry->symbolic_link_data != NULL )
264 		{
265 			memory_free(
266 			 internal_file_entry->symbolic_link_data );
267 		}
268 		if( internal_file_entry->directory_entries != NULL )
269 		{
270 			if( libcdata_array_free(
271 			     &( internal_file_entry->directory_entries ),
272 			     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
273 			     error ) != 1 )
274 			{
275 				libcerror_error_set(
276 				 error,
277 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
278 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
279 				 "%s: unable to free directory entries array.",
280 				 function );
281 
282 				result = -1;
283 			}
284 		}
285 		if( internal_file_entry->file_extents != NULL )
286 		{
287 			if( libcdata_array_free(
288 			     &( internal_file_entry->file_extents ),
289 			     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
290 			     error ) != 1 )
291 			{
292 				libcerror_error_set(
293 				 error,
294 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
295 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
296 				 "%s: unable to free file extents array.",
297 				 function );
298 
299 				result = -1;
300 			}
301 		}
302 		if( internal_file_entry->data_stream != NULL )
303 		{
304 			if( libfdata_stream_free(
305 			     &( internal_file_entry->data_stream ),
306 			     error ) != 1 )
307 			{
308 				libcerror_error_set(
309 				 error,
310 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
311 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
312 				 "%s: unable to free data stream.",
313 				 function );
314 
315 				result = -1;
316 			}
317 		}
318 		memory_free(
319 		 internal_file_entry );
320 	}
321 	return( result );
322 }
323 
324 /* Retrieves the identifier
325  * This value is retrieved from the inode
326  * Returns 1 if successful or -1 on error
327  */
libfsapfs_file_entry_get_identifier(libfsapfs_file_entry_t * file_entry,uint64_t * identifier,libcerror_error_t ** error)328 int libfsapfs_file_entry_get_identifier(
329      libfsapfs_file_entry_t *file_entry,
330      uint64_t *identifier,
331      libcerror_error_t **error )
332 {
333 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
334 	static char *function                                = "libfsapfs_file_entry_get_identifier";
335 	int result                                           = 1;
336 
337 	if( file_entry == NULL )
338 	{
339 		libcerror_error_set(
340 		 error,
341 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
342 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
343 		 "%s: invalid file entry.",
344 		 function );
345 
346 		return( -1 );
347 	}
348 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
349 
350 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
351 	if( libcthreads_read_write_lock_grab_for_read(
352 	     internal_file_entry->read_write_lock,
353 	     error ) != 1 )
354 	{
355 		libcerror_error_set(
356 		 error,
357 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
358 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
359 		 "%s: unable to grab read/write lock for reading.",
360 		 function );
361 
362 		return( -1 );
363 	}
364 #endif
365 	if( libfsapfs_inode_get_identifier(
366 	     internal_file_entry->inode,
367 	     identifier,
368 	     error ) != 1 )
369 	{
370 		libcerror_error_set(
371 		 error,
372 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
373 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
374 		 "%s: unable to retrieve identifier.",
375 		 function );
376 
377 		result = -1;
378 	}
379 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
380 	if( libcthreads_read_write_lock_release_for_read(
381 	     internal_file_entry->read_write_lock,
382 	     error ) != 1 )
383 	{
384 		libcerror_error_set(
385 		 error,
386 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
387 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
388 		 "%s: unable to release read/write lock for reading.",
389 		 function );
390 
391 		return( -1 );
392 	}
393 #endif
394 	return( result );
395 }
396 
397 /* Retrieves the parent identifier
398  * This value is retrieved from the inode
399  * Returns 1 if successful or -1 on error
400  */
libfsapfs_file_entry_get_parent_identifier(libfsapfs_file_entry_t * file_entry,uint64_t * parent_identifier,libcerror_error_t ** error)401 int libfsapfs_file_entry_get_parent_identifier(
402      libfsapfs_file_entry_t *file_entry,
403      uint64_t *parent_identifier,
404      libcerror_error_t **error )
405 {
406 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
407 	static char *function                                = "libfsapfs_file_entry_get_parent_identifier";
408 	int result                                           = 1;
409 
410 	if( file_entry == NULL )
411 	{
412 		libcerror_error_set(
413 		 error,
414 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
415 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
416 		 "%s: invalid file entry.",
417 		 function );
418 
419 		return( -1 );
420 	}
421 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
422 
423 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
424 	if( libcthreads_read_write_lock_grab_for_read(
425 	     internal_file_entry->read_write_lock,
426 	     error ) != 1 )
427 	{
428 		libcerror_error_set(
429 		 error,
430 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
431 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
432 		 "%s: unable to grab read/write lock for reading.",
433 		 function );
434 
435 		return( -1 );
436 	}
437 #endif
438 	if( libfsapfs_inode_get_parent_identifier(
439 	     internal_file_entry->inode,
440 	     parent_identifier,
441 	     error ) != 1 )
442 	{
443 		libcerror_error_set(
444 		 error,
445 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
446 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
447 		 "%s: unable to retrieve parent identifier.",
448 		 function );
449 
450 		result = -1;
451 	}
452 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
453 	if( libcthreads_read_write_lock_release_for_read(
454 	     internal_file_entry->read_write_lock,
455 	     error ) != 1 )
456 	{
457 		libcerror_error_set(
458 		 error,
459 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
460 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
461 		 "%s: unable to release read/write lock for reading.",
462 		 function );
463 
464 		return( -1 );
465 	}
466 #endif
467 	return( result );
468 }
469 
470 /* Retrieves the parent file entry
471  * Returns 1 if successful, 0 if no such file entry or -1 on error
472  */
libfsapfs_file_entry_get_parent_file_entry(libfsapfs_file_entry_t * file_entry,libfsapfs_file_entry_t ** parent_file_entry,libcerror_error_t ** error)473 int libfsapfs_file_entry_get_parent_file_entry(
474      libfsapfs_file_entry_t *file_entry,
475      libfsapfs_file_entry_t **parent_file_entry,
476      libcerror_error_t **error )
477 {
478 	libfsapfs_inode_t *inode                             = NULL;
479 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
480 	static char *function                                = "libfsapfs_file_entry_get_parent_file_entry";
481 	int result                                           = 0;
482 	uint64_t file_system_identifier                      = 0;
483 
484 	if( file_entry == NULL )
485 	{
486 		libcerror_error_set(
487 		 error,
488 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
489 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
490 		 "%s: invalid file entry.",
491 		 function );
492 
493 		return( -1 );
494 	}
495 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
496 
497 	if( parent_file_entry == NULL )
498 	{
499 		libcerror_error_set(
500 		 error,
501 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
502 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
503 		 "%s: invalid parent file entry.",
504 		 function );
505 
506 		return( -1 );
507 	}
508 	if( *parent_file_entry != NULL )
509 	{
510 		libcerror_error_set(
511 		 error,
512 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
513 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
514 		 "%s: invalid parent file entry value already set.",
515 		 function );
516 
517 		return( -1 );
518 	}
519 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
520 	if( libcthreads_read_write_lock_grab_for_write(
521 	     internal_file_entry->read_write_lock,
522 	     error ) != 1 )
523 	{
524 		libcerror_error_set(
525 		 error,
526 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
527 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
528 		 "%s: unable to grab read/write lock for writing.",
529 		 function );
530 
531 		return( -1 );
532 	}
533 #endif
534 	if( libfsapfs_inode_get_identifier(
535 	     internal_file_entry->inode,
536 	     &file_system_identifier,
537 	     error ) != 1 )
538 	{
539 		libcerror_error_set(
540 		 error,
541 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
542 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
543 		 "%s: unable to retrieve identifier.",
544 		 function );
545 
546 		goto on_error;
547 	}
548 	if( file_system_identifier > 2 )
549 	{
550 		if( libfsapfs_inode_get_parent_identifier(
551 		     internal_file_entry->inode,
552 		     &file_system_identifier,
553 		     error ) != 1 )
554 		{
555 			libcerror_error_set(
556 			 error,
557 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
558 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
559 			 "%s: unable to retrieve parent identifier.",
560 			 function );
561 
562 			goto on_error;
563 		}
564 		if( libfsapfs_file_system_btree_get_inode_by_identifier(
565 		     internal_file_entry->file_system_btree,
566 		     internal_file_entry->file_io_handle,
567 		     file_system_identifier,
568 		     &inode,
569 		     error ) != 1 )
570 		{
571 			libcerror_error_set(
572 			 error,
573 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
574 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
575 			 "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
576 			 function,
577 			 file_system_identifier );
578 
579 			 goto on_error;
580 		}
581 		if( libfsapfs_file_entry_initialize(
582 		     parent_file_entry,
583 		     internal_file_entry->io_handle,
584 		     internal_file_entry->file_io_handle,
585 		     internal_file_entry->encryption_context,
586 		     internal_file_entry->file_system_btree,
587 		     inode,
588 		     NULL,
589 		     error ) != 1 )
590 		{
591 			libcerror_error_set(
592 			 error,
593 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
594 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
595 			 "%s: unable to create file entry.",
596 			 function );
597 
598 			goto on_error;
599 		}
600 		inode  = NULL;
601 		result = 1;
602 	}
603 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
604 	if( libcthreads_read_write_lock_release_for_write(
605 	     internal_file_entry->read_write_lock,
606 	     error ) != 1 )
607 	{
608 		libcerror_error_set(
609 		 error,
610 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
611 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
612 		 "%s: unable to release read/write lock for writing.",
613 		 function );
614 
615 		return( -1 );
616 	}
617 #endif
618 	return( result );
619 
620 on_error:
621 	if( inode != NULL )
622 	{
623 		libfsapfs_inode_free(
624 		 &inode,
625 		 NULL );
626 	}
627 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
628 	libcthreads_read_write_lock_release_for_write(
629 	 internal_file_entry->read_write_lock,
630 	 NULL );
631 #endif
632 	return( -1 );
633 }
634 
635 /* Retrieves the creation date and time
636  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
637  * This value is retrieved from the inode
638  * Returns 1 if successful or -1 on error
639  */
libfsapfs_file_entry_get_creation_time(libfsapfs_file_entry_t * file_entry,int64_t * posix_time,libcerror_error_t ** error)640 int libfsapfs_file_entry_get_creation_time(
641      libfsapfs_file_entry_t *file_entry,
642      int64_t *posix_time,
643      libcerror_error_t **error )
644 {
645 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
646 	static char *function                                = "libfsapfs_file_entry_get_creation_time";
647 	int result                                           = 1;
648 
649 	if( file_entry == NULL )
650 	{
651 		libcerror_error_set(
652 		 error,
653 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
654 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
655 		 "%s: invalid file entry.",
656 		 function );
657 
658 		return( -1 );
659 	}
660 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
661 
662 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
663 	if( libcthreads_read_write_lock_grab_for_read(
664 	     internal_file_entry->read_write_lock,
665 	     error ) != 1 )
666 	{
667 		libcerror_error_set(
668 		 error,
669 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
670 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
671 		 "%s: unable to grab read/write lock for reading.",
672 		 function );
673 
674 		return( -1 );
675 	}
676 #endif
677 	if( libfsapfs_inode_get_creation_time(
678 	     internal_file_entry->inode,
679 	     posix_time,
680 	     error ) != 1 )
681 	{
682 		libcerror_error_set(
683 		 error,
684 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
685 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
686 		 "%s: unable to retrieve creation time.",
687 		 function );
688 
689 		result = -1;
690 	}
691 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
692 	if( libcthreads_read_write_lock_release_for_read(
693 	     internal_file_entry->read_write_lock,
694 	     error ) != 1 )
695 	{
696 		libcerror_error_set(
697 		 error,
698 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
699 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
700 		 "%s: unable to release read/write lock for reading.",
701 		 function );
702 
703 		return( -1 );
704 	}
705 #endif
706 	return( result );
707 }
708 
709 /* Retrieves the modification date and time
710  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
711  * This value is retrieved from the inode
712  * Returns 1 if successful or -1 on error
713  */
libfsapfs_file_entry_get_modification_time(libfsapfs_file_entry_t * file_entry,int64_t * posix_time,libcerror_error_t ** error)714 int libfsapfs_file_entry_get_modification_time(
715      libfsapfs_file_entry_t *file_entry,
716      int64_t *posix_time,
717      libcerror_error_t **error )
718 {
719 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
720 	static char *function                                = "libfsapfs_file_entry_get_modification_time";
721 	int result                                           = 1;
722 
723 	if( file_entry == NULL )
724 	{
725 		libcerror_error_set(
726 		 error,
727 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
728 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
729 		 "%s: invalid file entry.",
730 		 function );
731 
732 		return( -1 );
733 	}
734 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
735 
736 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
737 	if( libcthreads_read_write_lock_grab_for_read(
738 	     internal_file_entry->read_write_lock,
739 	     error ) != 1 )
740 	{
741 		libcerror_error_set(
742 		 error,
743 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
744 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
745 		 "%s: unable to grab read/write lock for reading.",
746 		 function );
747 
748 		return( -1 );
749 	}
750 #endif
751 	if( libfsapfs_inode_get_modification_time(
752 	     internal_file_entry->inode,
753 	     posix_time,
754 	     error ) != 1 )
755 	{
756 		libcerror_error_set(
757 		 error,
758 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
759 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
760 		 "%s: unable to retrieve modification time.",
761 		 function );
762 
763 		result = -1;
764 	}
765 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
766 	if( libcthreads_read_write_lock_release_for_read(
767 	     internal_file_entry->read_write_lock,
768 	     error ) != 1 )
769 	{
770 		libcerror_error_set(
771 		 error,
772 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
773 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
774 		 "%s: unable to release read/write lock for reading.",
775 		 function );
776 
777 		return( -1 );
778 	}
779 #endif
780 	return( result );
781 }
782 
783 /* Retrieves the access date and time
784  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
785  * This value is retrieved from the inode
786  * Returns 1 if successful or -1 on error
787  */
libfsapfs_file_entry_get_access_time(libfsapfs_file_entry_t * file_entry,int64_t * posix_time,libcerror_error_t ** error)788 int libfsapfs_file_entry_get_access_time(
789      libfsapfs_file_entry_t *file_entry,
790      int64_t *posix_time,
791      libcerror_error_t **error )
792 {
793 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
794 	static char *function                                = "libfsapfs_file_entry_get_access_time";
795 	int result                                           = 1;
796 
797 	if( file_entry == NULL )
798 	{
799 		libcerror_error_set(
800 		 error,
801 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
802 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
803 		 "%s: invalid file entry.",
804 		 function );
805 
806 		return( -1 );
807 	}
808 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
809 
810 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
811 	if( libcthreads_read_write_lock_grab_for_read(
812 	     internal_file_entry->read_write_lock,
813 	     error ) != 1 )
814 	{
815 		libcerror_error_set(
816 		 error,
817 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
818 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
819 		 "%s: unable to grab read/write lock for reading.",
820 		 function );
821 
822 		return( -1 );
823 	}
824 #endif
825 	if( libfsapfs_inode_get_access_time(
826 	     internal_file_entry->inode,
827 	     posix_time,
828 	     error ) != 1 )
829 	{
830 		libcerror_error_set(
831 		 error,
832 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
833 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
834 		 "%s: unable to retrieve access time.",
835 		 function );
836 
837 		result = -1;
838 	}
839 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
840 	if( libcthreads_read_write_lock_release_for_read(
841 	     internal_file_entry->read_write_lock,
842 	     error ) != 1 )
843 	{
844 		libcerror_error_set(
845 		 error,
846 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
847 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
848 		 "%s: unable to release read/write lock for reading.",
849 		 function );
850 
851 		return( -1 );
852 	}
853 #endif
854 	return( result );
855 }
856 
857 /* Retrieves the inode change date and time
858  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
859  * This value is retrieved from the inode
860  * Returns 1 if successful or -1 on error
861  */
libfsapfs_file_entry_get_inode_change_time(libfsapfs_file_entry_t * file_entry,int64_t * posix_time,libcerror_error_t ** error)862 int libfsapfs_file_entry_get_inode_change_time(
863      libfsapfs_file_entry_t *file_entry,
864      int64_t *posix_time,
865      libcerror_error_t **error )
866 {
867 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
868 	static char *function                                = "libfsapfs_file_entry_get_inode_change_time";
869 	int result                                           = 1;
870 
871 	if( file_entry == NULL )
872 	{
873 		libcerror_error_set(
874 		 error,
875 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
876 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
877 		 "%s: invalid file entry.",
878 		 function );
879 
880 		return( -1 );
881 	}
882 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
883 
884 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
885 	if( libcthreads_read_write_lock_grab_for_read(
886 	     internal_file_entry->read_write_lock,
887 	     error ) != 1 )
888 	{
889 		libcerror_error_set(
890 		 error,
891 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
892 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
893 		 "%s: unable to grab read/write lock for reading.",
894 		 function );
895 
896 		return( -1 );
897 	}
898 #endif
899 	if( libfsapfs_inode_get_inode_change_time(
900 	     internal_file_entry->inode,
901 	     posix_time,
902 	     error ) != 1 )
903 	{
904 		libcerror_error_set(
905 		 error,
906 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
907 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
908 		 "%s: unable to retrieve inode change time.",
909 		 function );
910 
911 		result = -1;
912 	}
913 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
914 	if( libcthreads_read_write_lock_release_for_read(
915 	     internal_file_entry->read_write_lock,
916 	     error ) != 1 )
917 	{
918 		libcerror_error_set(
919 		 error,
920 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
921 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
922 		 "%s: unable to release read/write lock for reading.",
923 		 function );
924 
925 		return( -1 );
926 	}
927 #endif
928 	return( result );
929 }
930 
931 /* Retrieves the added date and time
932  * The timestamp is a signed 64-bit POSIX date and time value in number of nano seconds
933  * This value is retrieved from the directory record
934  * Returns 1 if successful, 0 if not available or -1 on error
935  */
libfsapfs_file_entry_get_added_time(libfsapfs_file_entry_t * file_entry,int64_t * posix_time,libcerror_error_t ** error)936 int libfsapfs_file_entry_get_added_time(
937      libfsapfs_file_entry_t *file_entry,
938      int64_t *posix_time,
939      libcerror_error_t **error )
940 {
941 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
942 	static char *function                                = "libfsapfs_file_entry_get_added_time";
943 	int result                                           = 0;
944 
945 	if( file_entry == NULL )
946 	{
947 		libcerror_error_set(
948 		 error,
949 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
950 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
951 		 "%s: invalid file entry.",
952 		 function );
953 
954 		return( -1 );
955 	}
956 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
957 
958 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
959 	if( libcthreads_read_write_lock_grab_for_read(
960 	     internal_file_entry->read_write_lock,
961 	     error ) != 1 )
962 	{
963 		libcerror_error_set(
964 		 error,
965 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
966 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
967 		 "%s: unable to grab read/write lock for reading.",
968 		 function );
969 
970 		return( -1 );
971 	}
972 #endif
973 	if( internal_file_entry->directory_record != NULL )
974 	{
975 		result = libfsapfs_directory_record_get_added_time(
976 		          internal_file_entry->directory_record,
977 		          posix_time,
978 		          error );
979 
980 		if( result != 1 )
981 		{
982 			libcerror_error_set(
983 			 error,
984 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
985 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
986 			 "%s: unable to retrieve added time.",
987 			 function );
988 
989 			result = -1;
990 		}
991 	}
992 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
993 	if( libcthreads_read_write_lock_release_for_read(
994 	     internal_file_entry->read_write_lock,
995 	     error ) != 1 )
996 	{
997 		libcerror_error_set(
998 		 error,
999 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1000 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1001 		 "%s: unable to release read/write lock for reading.",
1002 		 function );
1003 
1004 		return( -1 );
1005 	}
1006 #endif
1007 	return( result );
1008 }
1009 
1010 /* Retrieves the owner identifier
1011  * This value is retrieved from the inode
1012  * Returns 1 if successful or -1 on error
1013  */
libfsapfs_file_entry_get_owner_identifier(libfsapfs_file_entry_t * file_entry,uint32_t * owner_identifier,libcerror_error_t ** error)1014 int libfsapfs_file_entry_get_owner_identifier(
1015      libfsapfs_file_entry_t *file_entry,
1016      uint32_t *owner_identifier,
1017      libcerror_error_t **error )
1018 {
1019 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1020 	static char *function                                = "libfsapfs_file_entry_get_owner_identifier";
1021 	int result                                           = 1;
1022 
1023 	if( file_entry == NULL )
1024 	{
1025 		libcerror_error_set(
1026 		 error,
1027 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1028 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1029 		 "%s: invalid file entry.",
1030 		 function );
1031 
1032 		return( -1 );
1033 	}
1034 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1035 
1036 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1037 	if( libcthreads_read_write_lock_grab_for_read(
1038 	     internal_file_entry->read_write_lock,
1039 	     error ) != 1 )
1040 	{
1041 		libcerror_error_set(
1042 		 error,
1043 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1044 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1045 		 "%s: unable to grab read/write lock for reading.",
1046 		 function );
1047 
1048 		return( -1 );
1049 	}
1050 #endif
1051 	if( libfsapfs_inode_get_owner_identifier(
1052 	     internal_file_entry->inode,
1053 	     owner_identifier,
1054 	     error ) != 1 )
1055 	{
1056 		libcerror_error_set(
1057 		 error,
1058 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1060 		 "%s: unable to retrieve owner identifier.",
1061 		 function );
1062 
1063 		result = -1;
1064 	}
1065 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1066 	if( libcthreads_read_write_lock_release_for_read(
1067 	     internal_file_entry->read_write_lock,
1068 	     error ) != 1 )
1069 	{
1070 		libcerror_error_set(
1071 		 error,
1072 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1073 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1074 		 "%s: unable to release read/write lock for reading.",
1075 		 function );
1076 
1077 		return( -1 );
1078 	}
1079 #endif
1080 	return( result );
1081 }
1082 
1083 /* Retrieves the group identifier
1084  * This value is retrieved from the inode
1085  * Returns 1 if successful or -1 on error
1086  */
libfsapfs_file_entry_get_group_identifier(libfsapfs_file_entry_t * file_entry,uint32_t * group_identifier,libcerror_error_t ** error)1087 int libfsapfs_file_entry_get_group_identifier(
1088      libfsapfs_file_entry_t *file_entry,
1089      uint32_t *group_identifier,
1090      libcerror_error_t **error )
1091 {
1092 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1093 	static char *function                                = "libfsapfs_file_entry_get_group_identifier";
1094 	int result                                           = 1;
1095 
1096 	if( file_entry == NULL )
1097 	{
1098 		libcerror_error_set(
1099 		 error,
1100 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1101 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1102 		 "%s: invalid file entry.",
1103 		 function );
1104 
1105 		return( -1 );
1106 	}
1107 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1108 
1109 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1110 	if( libcthreads_read_write_lock_grab_for_read(
1111 	     internal_file_entry->read_write_lock,
1112 	     error ) != 1 )
1113 	{
1114 		libcerror_error_set(
1115 		 error,
1116 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1117 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1118 		 "%s: unable to grab read/write lock for reading.",
1119 		 function );
1120 
1121 		return( -1 );
1122 	}
1123 #endif
1124 	if( libfsapfs_inode_get_group_identifier(
1125 	     internal_file_entry->inode,
1126 	     group_identifier,
1127 	     error ) != 1 )
1128 	{
1129 		libcerror_error_set(
1130 		 error,
1131 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1132 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1133 		 "%s: unable to retrieve group identifier.",
1134 		 function );
1135 
1136 		result = -1;
1137 	}
1138 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1139 	if( libcthreads_read_write_lock_release_for_read(
1140 	     internal_file_entry->read_write_lock,
1141 	     error ) != 1 )
1142 	{
1143 		libcerror_error_set(
1144 		 error,
1145 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1146 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1147 		 "%s: unable to release read/write lock for reading.",
1148 		 function );
1149 
1150 		return( -1 );
1151 	}
1152 #endif
1153 	return( result );
1154 }
1155 
1156 /* Retrieves the file mode
1157  * This value is retrieved from the inode
1158  * Returns 1 if successful or -1 on error
1159  */
libfsapfs_file_entry_get_file_mode(libfsapfs_file_entry_t * file_entry,uint16_t * file_mode,libcerror_error_t ** error)1160 int libfsapfs_file_entry_get_file_mode(
1161      libfsapfs_file_entry_t *file_entry,
1162      uint16_t *file_mode,
1163      libcerror_error_t **error )
1164 {
1165 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1166 	static char *function                                = "libfsapfs_file_entry_get_file_mode";
1167 	int result                                           = 1;
1168 
1169 	if( file_entry == NULL )
1170 	{
1171 		libcerror_error_set(
1172 		 error,
1173 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1174 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1175 		 "%s: invalid file entry.",
1176 		 function );
1177 
1178 		return( -1 );
1179 	}
1180 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1181 
1182 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1183 	if( libcthreads_read_write_lock_grab_for_read(
1184 	     internal_file_entry->read_write_lock,
1185 	     error ) != 1 )
1186 	{
1187 		libcerror_error_set(
1188 		 error,
1189 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1190 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1191 		 "%s: unable to grab read/write lock for reading.",
1192 		 function );
1193 
1194 		return( -1 );
1195 	}
1196 #endif
1197 	if( libfsapfs_inode_get_file_mode(
1198 	     internal_file_entry->inode,
1199 	     file_mode,
1200 	     error ) != 1 )
1201 	{
1202 		libcerror_error_set(
1203 		 error,
1204 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1205 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1206 		 "%s: unable to retrieve file mode.",
1207 		 function );
1208 
1209 		result = -1;
1210 	}
1211 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1212 	if( libcthreads_read_write_lock_release_for_read(
1213 	     internal_file_entry->read_write_lock,
1214 	     error ) != 1 )
1215 	{
1216 		libcerror_error_set(
1217 		 error,
1218 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1219 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1220 		 "%s: unable to release read/write lock for reading.",
1221 		 function );
1222 
1223 		return( -1 );
1224 	}
1225 #endif
1226 	return( result );
1227 }
1228 
1229 /* Retrieves the size of the UTF-8 encoded name
1230  * The returned size includes the end of string character
1231  * This value is retrieved from the inode
1232  * Returns 1 if successful or -1 on error
1233  */
libfsapfs_file_entry_get_utf8_name_size(libfsapfs_file_entry_t * file_entry,size_t * utf8_string_size,libcerror_error_t ** error)1234 int libfsapfs_file_entry_get_utf8_name_size(
1235      libfsapfs_file_entry_t *file_entry,
1236      size_t *utf8_string_size,
1237      libcerror_error_t **error )
1238 {
1239 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1240 	static char *function                                = "libfsapfs_file_entry_get_utf8_name_size";
1241 	int result                                           = 1;
1242 
1243 	if( file_entry == NULL )
1244 	{
1245 		libcerror_error_set(
1246 		 error,
1247 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1248 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1249 		 "%s: invalid file entry.",
1250 		 function );
1251 
1252 		return( -1 );
1253 	}
1254 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1255 
1256 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1257 	if( libcthreads_read_write_lock_grab_for_read(
1258 	     internal_file_entry->read_write_lock,
1259 	     error ) != 1 )
1260 	{
1261 		libcerror_error_set(
1262 		 error,
1263 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1264 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1265 		 "%s: unable to grab read/write lock for reading.",
1266 		 function );
1267 
1268 		return( -1 );
1269 	}
1270 #endif
1271 	if( internal_file_entry->directory_record != NULL )
1272 	{
1273 		if( libfsapfs_directory_record_get_utf8_name_size(
1274 		     internal_file_entry->directory_record,
1275 		     utf8_string_size,
1276 		     error ) != 1 )
1277 		{
1278 			libcerror_error_set(
1279 			 error,
1280 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1281 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1282 			 "%s: unable to retrieve UTF-8 string size from directory record.",
1283 			 function );
1284 
1285 			result = -1;
1286 		}
1287 	}
1288 	else
1289 	{
1290 		if( libfsapfs_inode_get_utf8_name_size(
1291 		     internal_file_entry->inode,
1292 		     utf8_string_size,
1293 		     error ) != 1 )
1294 		{
1295 			libcerror_error_set(
1296 			 error,
1297 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1299 			 "%s: unable to retrieve UTF-8 string size from inode.",
1300 			 function );
1301 
1302 			result = -1;
1303 		}
1304 	}
1305 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1306 	if( libcthreads_read_write_lock_release_for_read(
1307 	     internal_file_entry->read_write_lock,
1308 	     error ) != 1 )
1309 	{
1310 		libcerror_error_set(
1311 		 error,
1312 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1313 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1314 		 "%s: unable to release read/write lock for reading.",
1315 		 function );
1316 
1317 		return( -1 );
1318 	}
1319 #endif
1320 	return( result );
1321 }
1322 
1323 /* Retrieves the UTF-8 encoded name
1324  * The size should include the end of string character
1325  * This value is retrieved from the inode
1326  * Returns 1 if successful or -1 on error
1327  */
libfsapfs_file_entry_get_utf8_name(libfsapfs_file_entry_t * file_entry,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1328 int libfsapfs_file_entry_get_utf8_name(
1329      libfsapfs_file_entry_t *file_entry,
1330      uint8_t *utf8_string,
1331      size_t utf8_string_size,
1332      libcerror_error_t **error )
1333 {
1334 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1335 	static char *function                                = "libfsapfs_file_entry_get_utf8_name";
1336 	int result                                           = 1;
1337 
1338 	if( file_entry == NULL )
1339 	{
1340 		libcerror_error_set(
1341 		 error,
1342 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1343 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1344 		 "%s: invalid file entry.",
1345 		 function );
1346 
1347 		return( -1 );
1348 	}
1349 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1350 
1351 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1352 	if( libcthreads_read_write_lock_grab_for_read(
1353 	     internal_file_entry->read_write_lock,
1354 	     error ) != 1 )
1355 	{
1356 		libcerror_error_set(
1357 		 error,
1358 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1359 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1360 		 "%s: unable to grab read/write lock for reading.",
1361 		 function );
1362 
1363 		return( -1 );
1364 	}
1365 #endif
1366 	if( internal_file_entry->directory_record != NULL )
1367 	{
1368 		if( libfsapfs_directory_record_get_utf8_name(
1369 		     internal_file_entry->directory_record,
1370 		     utf8_string,
1371 		     utf8_string_size,
1372 		     error ) != 1 )
1373 		{
1374 			libcerror_error_set(
1375 			 error,
1376 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1377 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1378 			 "%s: unable to retrieve UTF-8 string from directory entry.",
1379 			 function );
1380 
1381 			result = -1;
1382 		}
1383 	}
1384 	else
1385 	{
1386 		if( libfsapfs_inode_get_utf8_name(
1387 		     internal_file_entry->inode,
1388 		     utf8_string,
1389 		     utf8_string_size,
1390 		     error ) != 1 )
1391 		{
1392 			libcerror_error_set(
1393 			 error,
1394 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1395 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1396 			 "%s: unable to retrieve UTF-8 string from inode.",
1397 			 function );
1398 
1399 			result = -1;
1400 		}
1401 	}
1402 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1403 	if( libcthreads_read_write_lock_release_for_read(
1404 	     internal_file_entry->read_write_lock,
1405 	     error ) != 1 )
1406 	{
1407 		libcerror_error_set(
1408 		 error,
1409 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1410 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1411 		 "%s: unable to release read/write lock for reading.",
1412 		 function );
1413 
1414 		return( -1 );
1415 	}
1416 #endif
1417 	return( result );
1418 }
1419 
1420 /* Retrieves the size of the UTF-16 encoded name
1421  * The returned size includes the end of string character
1422  * This value is retrieved from the inode
1423  * Returns 1 if successful or -1 on error
1424  */
libfsapfs_file_entry_get_utf16_name_size(libfsapfs_file_entry_t * file_entry,size_t * utf16_string_size,libcerror_error_t ** error)1425 int libfsapfs_file_entry_get_utf16_name_size(
1426      libfsapfs_file_entry_t *file_entry,
1427      size_t *utf16_string_size,
1428      libcerror_error_t **error )
1429 {
1430 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1431 	static char *function                                = "libfsapfs_file_entry_get_utf16_name_size";
1432 	int result                                           = 1;
1433 
1434 	if( file_entry == NULL )
1435 	{
1436 		libcerror_error_set(
1437 		 error,
1438 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1439 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1440 		 "%s: invalid file entry.",
1441 		 function );
1442 
1443 		return( -1 );
1444 	}
1445 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1446 
1447 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1448 	if( libcthreads_read_write_lock_grab_for_read(
1449 	     internal_file_entry->read_write_lock,
1450 	     error ) != 1 )
1451 	{
1452 		libcerror_error_set(
1453 		 error,
1454 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1455 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1456 		 "%s: unable to grab read/write lock for reading.",
1457 		 function );
1458 
1459 		return( -1 );
1460 	}
1461 #endif
1462 	if( internal_file_entry->directory_record != NULL )
1463 	{
1464 		if( libfsapfs_directory_record_get_utf16_name_size(
1465 		     internal_file_entry->directory_record,
1466 		     utf16_string_size,
1467 		     error ) != 1 )
1468 		{
1469 			libcerror_error_set(
1470 			 error,
1471 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1472 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1473 			 "%s: unable to retrieve UTF-16 string size from directory record.",
1474 			 function );
1475 
1476 			result = -1;
1477 		}
1478 	}
1479 	else
1480 	{
1481 		if( libfsapfs_inode_get_utf16_name_size(
1482 		     internal_file_entry->inode,
1483 		     utf16_string_size,
1484 		     error ) != 1 )
1485 		{
1486 			libcerror_error_set(
1487 			 error,
1488 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1489 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1490 			 "%s: unable to retrieve UTF-16 string size from inode.",
1491 			 function );
1492 
1493 			result = -1;
1494 		}
1495 	}
1496 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1497 	if( libcthreads_read_write_lock_release_for_read(
1498 	     internal_file_entry->read_write_lock,
1499 	     error ) != 1 )
1500 	{
1501 		libcerror_error_set(
1502 		 error,
1503 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1504 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1505 		 "%s: unable to release read/write lock for reading.",
1506 		 function );
1507 
1508 		return( -1 );
1509 	}
1510 #endif
1511 	return( result );
1512 }
1513 
1514 /* Retrieves the UTF-16 encoded name
1515  * The size should include the end of string character
1516  * This value is retrieved from the inode
1517  * Returns 1 if successful or -1 on error
1518  */
libfsapfs_file_entry_get_utf16_name(libfsapfs_file_entry_t * file_entry,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)1519 int libfsapfs_file_entry_get_utf16_name(
1520      libfsapfs_file_entry_t *file_entry,
1521      uint16_t *utf16_string,
1522      size_t utf16_string_size,
1523      libcerror_error_t **error )
1524 {
1525 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1526 	static char *function                                = "libfsapfs_file_entry_get_utf16_name";
1527 	int result                                           = 1;
1528 
1529 	if( file_entry == NULL )
1530 	{
1531 		libcerror_error_set(
1532 		 error,
1533 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1534 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1535 		 "%s: invalid file entry.",
1536 		 function );
1537 
1538 		return( -1 );
1539 	}
1540 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1541 
1542 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1543 	if( libcthreads_read_write_lock_grab_for_read(
1544 	     internal_file_entry->read_write_lock,
1545 	     error ) != 1 )
1546 	{
1547 		libcerror_error_set(
1548 		 error,
1549 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1550 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1551 		 "%s: unable to grab read/write lock for reading.",
1552 		 function );
1553 
1554 		return( -1 );
1555 	}
1556 #endif
1557 	if( internal_file_entry->directory_record != NULL )
1558 	{
1559 		if( libfsapfs_directory_record_get_utf16_name(
1560 		     internal_file_entry->directory_record,
1561 		     utf16_string,
1562 		     utf16_string_size,
1563 		     error ) != 1 )
1564 		{
1565 			libcerror_error_set(
1566 			 error,
1567 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1568 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1569 			 "%s: unable to retrieve UTF-16 string from directory record.",
1570 			 function );
1571 
1572 			result = -1;
1573 		}
1574 	}
1575 	else
1576 	{
1577 		if( libfsapfs_inode_get_utf16_name(
1578 		     internal_file_entry->inode,
1579 		     utf16_string,
1580 		     utf16_string_size,
1581 		     error ) != 1 )
1582 		{
1583 			libcerror_error_set(
1584 			 error,
1585 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1586 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1587 			 "%s: unable to retrieve UTF-16 string from inode.",
1588 			 function );
1589 
1590 			result = -1;
1591 		}
1592 	}
1593 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1594 	if( libcthreads_read_write_lock_release_for_read(
1595 	     internal_file_entry->read_write_lock,
1596 	     error ) != 1 )
1597 	{
1598 		libcerror_error_set(
1599 		 error,
1600 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1601 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1602 		 "%s: unable to release read/write lock for reading.",
1603 		 function );
1604 
1605 		return( -1 );
1606 	}
1607 #endif
1608 	return( result );
1609 }
1610 
1611 /* Determines the extended attributes
1612  * Returns 1 if successful or -1 on error
1613  */
libfsapfs_internal_file_entry_get_extended_attributes(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)1614 int libfsapfs_internal_file_entry_get_extended_attributes(
1615      libfsapfs_internal_file_entry_t *internal_file_entry,
1616      libcerror_error_t **error )
1617 {
1618 	libfsapfs_extended_attribute_t *extended_attribute = NULL;
1619 	static char *function                              = "libfsapfs_internal_file_entry_get_extended_attributes";
1620 	uint64_t file_system_identifier                    = 0;
1621 	int extended_attribute_index                       = 0;
1622 	int number_of_extended_attributes                  = 0;
1623 	int result                                         = 0;
1624 
1625 	if( internal_file_entry == NULL )
1626 	{
1627 		libcerror_error_set(
1628 		 error,
1629 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1630 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1631 		 "%s: invalid file entry.",
1632 		 function );
1633 
1634 		return( -1 );
1635 	}
1636 	if( internal_file_entry->extended_attributes != NULL )
1637 	{
1638 		libcerror_error_set(
1639 		 error,
1640 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1641 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1642 		 "%s: invalid file entry - extended attributes value already set.",
1643 		 function );
1644 
1645 		return( -1 );
1646 	}
1647 	if( libfsapfs_inode_get_identifier(
1648 	     internal_file_entry->inode,
1649 	     &file_system_identifier,
1650 	     error ) != 1 )
1651 	{
1652 		libcerror_error_set(
1653 		 error,
1654 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1655 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1656 		 "%s: unable to retrieve identifier from inode.",
1657 		 function );
1658 
1659 		goto on_error;
1660 	}
1661 	if( libcdata_array_initialize(
1662 	     &( internal_file_entry->extended_attributes ),
1663 	     0,
1664 	     error ) != 1 )
1665 	{
1666 		libcerror_error_set(
1667 		 error,
1668 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1669 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1670 		 "%s: unable to create extended attributes array.",
1671 		 function );
1672 
1673 		goto on_error;
1674 	}
1675 	result = libfsapfs_file_system_btree_get_extended_attributes(
1676 		  internal_file_entry->file_system_btree,
1677 		  internal_file_entry->file_io_handle,
1678 		  file_system_identifier,
1679 		  internal_file_entry->extended_attributes,
1680 		  error );
1681 
1682 	if( result == -1 )
1683 	{
1684 		libcerror_error_set(
1685 		 error,
1686 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1687 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1688 		 "%s: unable to retrieve extended attributes from file system B-tree.",
1689 		 function );
1690 
1691 		goto on_error;
1692 	}
1693 	if( libcdata_array_get_number_of_entries(
1694 	     internal_file_entry->extended_attributes,
1695 	     &number_of_extended_attributes,
1696 	     error ) != 1 )
1697 	{
1698 		libcerror_error_set(
1699 		 error,
1700 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1701 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1702 		 "%s: unable to retrieve number of entries from extended attributes array.",
1703 		 function );
1704 
1705 		return( -1 );
1706 	}
1707 	for( extended_attribute_index = 0;
1708 	     extended_attribute_index < number_of_extended_attributes;
1709 	     extended_attribute_index++ )
1710 	{
1711 		if( libcdata_array_get_entry_by_index(
1712 		     internal_file_entry->extended_attributes,
1713 		     extended_attribute_index,
1714 		     (intptr_t **) &extended_attribute,
1715 		     error ) != 1 )
1716 		{
1717 			libcerror_error_set(
1718 			 error,
1719 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1720 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1721 			 "%s: unable to retrieve extended attribute: %d.",
1722 			 function,
1723 			 extended_attribute_index );
1724 
1725 			return( -1 );
1726 		}
1727 		result = libfsapfs_extended_attribute_compare_name_with_utf8_string(
1728 		          extended_attribute,
1729 		          (uint8_t *) "com.apple.decmpfs",
1730 		          17,
1731 		          error );
1732 
1733 		if( result == -1 )
1734 		{
1735 			libcerror_error_set(
1736 			 error,
1737 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1738 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1739 			 "%s: unable to compare UTF-8 string with name of extended attribute.",
1740 			 function );
1741 
1742 			return( -1 );
1743 		}
1744 		else if( result == LIBUNA_COMPARE_EQUAL )
1745 		{
1746 			internal_file_entry->compressed_data_extended_attribute = extended_attribute;
1747 
1748 			continue;
1749 		}
1750 		result = libfsapfs_extended_attribute_compare_name_with_utf8_string(
1751 		          extended_attribute,
1752 		          (uint8_t *) "com.apple.ResourceFork",
1753 		          22,
1754 		          error );
1755 
1756 		if( result == -1 )
1757 		{
1758 			libcerror_error_set(
1759 			 error,
1760 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1761 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1762 			 "%s: unable to compare UTF-8 string with name of extended attribute.",
1763 			 function );
1764 
1765 			return( -1 );
1766 		}
1767 		else if( result == LIBUNA_COMPARE_EQUAL )
1768 		{
1769 			internal_file_entry->resource_fork_extended_attribute = extended_attribute;
1770 
1771 			continue;
1772 		}
1773 		result = libfsapfs_extended_attribute_compare_name_with_utf8_string(
1774 		          extended_attribute,
1775 		          (uint8_t *) "com.apple.fs.symlink",
1776 		          20,
1777 		          error );
1778 
1779 		if( result == -1 )
1780 		{
1781 			libcerror_error_set(
1782 			 error,
1783 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1784 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1785 			 "%s: unable to compare UTF-8 string with name of extended attribute.",
1786 			 function );
1787 
1788 			return( -1 );
1789 		}
1790 		else if( result == LIBUNA_COMPARE_EQUAL )
1791 		{
1792 			internal_file_entry->symbolic_link_extended_attribute = extended_attribute;
1793 
1794 			continue;
1795 		}
1796 	}
1797 	return( 1 );
1798 
1799 on_error:
1800 	if( internal_file_entry->extended_attributes != NULL )
1801 	{
1802 		libcdata_array_free(
1803 		 &( internal_file_entry->extended_attributes ),
1804 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_internal_extended_attribute_free,
1805 		 NULL );
1806 	}
1807 	return( -1 );
1808 }
1809 
1810 /* Determines the symbolic link data
1811  * Returns 1 if successful or -1 on error
1812  */
libfsapfs_internal_file_entry_get_symbolic_link_data(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)1813 int libfsapfs_internal_file_entry_get_symbolic_link_data(
1814      libfsapfs_internal_file_entry_t *internal_file_entry,
1815      libcerror_error_t **error )
1816 {
1817 	static char *function            = "libfsapfs_internal_file_entry_get_symbolic_link_data";
1818 	size64_t extended_attribute_size = 0;
1819 	ssize_t read_count               = 0;
1820 
1821 	if( internal_file_entry == NULL )
1822 	{
1823 		libcerror_error_set(
1824 		 error,
1825 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1826 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1827 		 "%s: invalid file entry.",
1828 		 function );
1829 
1830 		return( -1 );
1831 	}
1832 	if( internal_file_entry->symbolic_link_data != NULL )
1833 	{
1834 		libcerror_error_set(
1835 		 error,
1836 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1837 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1838 		 "%s: invalid file entry - symbolic link data value already set.",
1839 		 function );
1840 
1841 		return( -1 );
1842 	}
1843 	if( internal_file_entry->extended_attributes == NULL )
1844 	{
1845 		if( libfsapfs_internal_file_entry_get_extended_attributes(
1846 		     internal_file_entry,
1847 		     error ) != 1 )
1848 		{
1849 			libcerror_error_set(
1850 			 error,
1851 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1852 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1853 			 "%s: unable to determine extended attributes.",
1854 			 function );
1855 
1856 			goto on_error;
1857 		}
1858 	}
1859 	if( internal_file_entry->symbolic_link_extended_attribute != NULL )
1860 	{
1861 		if( libfsapfs_extended_attribute_get_size(
1862 		     internal_file_entry->symbolic_link_extended_attribute,
1863 		     &extended_attribute_size,
1864 		     error ) != 1 )
1865 		{
1866 			libcerror_error_set(
1867 			 error,
1868 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1869 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1870 			 "%s: unable to retrieve extended attribute data size.",
1871 			 function );
1872 
1873 			goto on_error;
1874 		}
1875 		if( ( extended_attribute_size == 0 )
1876 		 || ( extended_attribute_size > (size64_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1877 		{
1878 			libcerror_error_set(
1879 			 error,
1880 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1881 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1882 			 "%s: invalid extended attribute data size value out of bounds.",
1883 			 function );
1884 
1885 			goto on_error;
1886 		}
1887 		internal_file_entry->symbolic_link_data = (uint8_t *) memory_allocate(
1888 		                                                       sizeof( uint8_t ) * extended_attribute_size );
1889 
1890 		if( internal_file_entry->symbolic_link_data == NULL )
1891 		{
1892 			libcerror_error_set(
1893 			 error,
1894 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1895 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1896 			 "%s: unable to create symbolic link data.",
1897 			 function );
1898 
1899 			goto on_error;
1900 		}
1901 		internal_file_entry->symbolic_link_data_size = (size_t) extended_attribute_size;
1902 
1903 		read_count = libfsapfs_extended_attribute_read_buffer_at_offset(
1904 		              internal_file_entry->symbolic_link_extended_attribute,
1905 		              internal_file_entry->symbolic_link_data,
1906 		              internal_file_entry->symbolic_link_data_size,
1907 		              0,
1908 		              error );
1909 
1910 		if( read_count != (ssize_t) internal_file_entry->symbolic_link_data_size )
1911 		{
1912 			libcerror_error_set(
1913 			 error,
1914 			 LIBCERROR_ERROR_DOMAIN_IO,
1915 			 LIBCERROR_IO_ERROR_READ_FAILED,
1916 			 "%s: unable to read extended attribute data.",
1917 			 function );
1918 
1919 			goto on_error;
1920 		}
1921 	}
1922 	return( 1 );
1923 
1924 on_error:
1925 	if( internal_file_entry->symbolic_link_data != NULL )
1926 	{
1927 		memory_free(
1928 		 internal_file_entry->symbolic_link_data );
1929 
1930 		internal_file_entry->symbolic_link_data = NULL;
1931 	}
1932 	internal_file_entry->symbolic_link_data_size = 0;
1933 
1934 	return( -1 );
1935 }
1936 
1937 /* Retrieves the size of the UTF-8 encoded symbolic link target
1938  * The size should include the end of string character
1939  * This value is retrieved from the com.apple.fs.symlink extended attribute
1940  * Returns 1 if successful, 0 if not available or -1 on error
1941  */
libfsapfs_file_entry_get_utf8_symbolic_link_target_size(libfsapfs_file_entry_t * file_entry,size_t * utf8_string_size,libcerror_error_t ** error)1942 int libfsapfs_file_entry_get_utf8_symbolic_link_target_size(
1943      libfsapfs_file_entry_t *file_entry,
1944      size_t *utf8_string_size,
1945      libcerror_error_t **error )
1946 {
1947 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
1948 	static char *function                                = "libfsapfs_file_entry_get_utf8_symbolic_link_target_size";
1949 	int result                                           = 0;
1950 
1951 	if( file_entry == NULL )
1952 	{
1953 		libcerror_error_set(
1954 		 error,
1955 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1956 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1957 		 "%s: invalid file entry.",
1958 		 function );
1959 
1960 		return( -1 );
1961 	}
1962 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
1963 
1964 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1965 	if( libcthreads_read_write_lock_grab_for_write(
1966 	     internal_file_entry->read_write_lock,
1967 	     error ) != 1 )
1968 	{
1969 		libcerror_error_set(
1970 		 error,
1971 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1972 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1973 		 "%s: unable to grab read/write lock for writing.",
1974 		 function );
1975 
1976 		return( -1 );
1977 	}
1978 #endif
1979 	if( internal_file_entry->symbolic_link_data == NULL )
1980 	{
1981 		if( libfsapfs_internal_file_entry_get_symbolic_link_data(
1982 		     internal_file_entry,
1983 		     error ) != 1 )
1984 		{
1985 			libcerror_error_set(
1986 			 error,
1987 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1988 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1989 			 "%s: unable to determine symbolic link data.",
1990 			 function );
1991 
1992 			goto on_error;
1993 		}
1994 	}
1995 	if( internal_file_entry->symbolic_link_data != NULL )
1996 	{
1997 		if( libuna_utf8_string_size_from_utf8_stream(
1998 		     internal_file_entry->symbolic_link_data,
1999 		     internal_file_entry->symbolic_link_data_size,
2000 		     utf8_string_size,
2001 		     error ) != 1 )
2002 		{
2003 			libcerror_error_set(
2004 			 error,
2005 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2006 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2007 			 "%s: unable to retrieve UTF-8 string size.",
2008 			 function );
2009 
2010 			goto on_error;
2011 		}
2012 		result = 1;
2013 	}
2014 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2015 	if( libcthreads_read_write_lock_release_for_write(
2016 	     internal_file_entry->read_write_lock,
2017 	     error ) != 1 )
2018 	{
2019 		libcerror_error_set(
2020 		 error,
2021 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2022 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2023 		 "%s: unable to release read/write lock for writing.",
2024 		 function );
2025 
2026 		return( -1 );
2027 	}
2028 #endif
2029 	return( result );
2030 
2031 on_error:
2032 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2033 	libcthreads_read_write_lock_release_for_write(
2034 	 internal_file_entry->read_write_lock,
2035 	 NULL );
2036 #endif
2037 	return( -1 );
2038 }
2039 
2040 /* Retrieves the UTF-8 encoded symbolic link target
2041  * The size should include the end of string character
2042  * This value is retrieved from the com.apple.fs.symlink extended attribute
2043  * Returns 1 if successful, 0 if not available or -1 on error
2044  */
libfsapfs_file_entry_get_utf8_symbolic_link_target(libfsapfs_file_entry_t * file_entry,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)2045 int libfsapfs_file_entry_get_utf8_symbolic_link_target(
2046      libfsapfs_file_entry_t *file_entry,
2047      uint8_t *utf8_string,
2048      size_t utf8_string_size,
2049      libcerror_error_t **error )
2050 {
2051 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2052 	static char *function                                = "libfsapfs_file_entry_get_utf8_symbolic_link_target";
2053 	int result                                           = 0;
2054 
2055 	if( file_entry == NULL )
2056 	{
2057 		libcerror_error_set(
2058 		 error,
2059 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2060 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2061 		 "%s: invalid file entry.",
2062 		 function );
2063 
2064 		return( -1 );
2065 	}
2066 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2067 
2068 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2069 	if( libcthreads_read_write_lock_grab_for_write(
2070 	     internal_file_entry->read_write_lock,
2071 	     error ) != 1 )
2072 	{
2073 		libcerror_error_set(
2074 		 error,
2075 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2076 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2077 		 "%s: unable to grab read/write lock for writing.",
2078 		 function );
2079 
2080 		return( -1 );
2081 	}
2082 #endif
2083 	if( internal_file_entry->symbolic_link_data == NULL )
2084 	{
2085 		if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2086 		     internal_file_entry,
2087 		     error ) != 1 )
2088 		{
2089 			libcerror_error_set(
2090 			 error,
2091 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2092 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2093 			 "%s: unable to determine symbolic link data.",
2094 			 function );
2095 
2096 			goto on_error;
2097 		}
2098 	}
2099 	if( internal_file_entry->symbolic_link_data != NULL )
2100 	{
2101 		if( libuna_utf8_string_copy_from_utf8_stream(
2102 		     utf8_string,
2103 		     utf8_string_size,
2104 		     internal_file_entry->symbolic_link_data,
2105 		     internal_file_entry->symbolic_link_data_size,
2106 		     error ) != 1 )
2107 		{
2108 			libcerror_error_set(
2109 			 error,
2110 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2111 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2112 			 "%s: unable to retrieve UTF-8 string.",
2113 			 function );
2114 
2115 			goto on_error;
2116 		}
2117 		result = 1;
2118 	}
2119 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2120 	if( libcthreads_read_write_lock_release_for_write(
2121 	     internal_file_entry->read_write_lock,
2122 	     error ) != 1 )
2123 	{
2124 		libcerror_error_set(
2125 		 error,
2126 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2127 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2128 		 "%s: unable to release read/write lock for writing.",
2129 		 function );
2130 
2131 		return( -1 );
2132 	}
2133 #endif
2134 	return( result );
2135 
2136 on_error:
2137 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2138 	libcthreads_read_write_lock_release_for_write(
2139 	 internal_file_entry->read_write_lock,
2140 	 NULL );
2141 #endif
2142 	return( -1 );
2143 }
2144 
2145 /* Retrieves the size of the UTF-16 encoded symbolic link target
2146  * The size should include the end of string character
2147  * This value is retrieved from the com.apple.fs.symlink extended attribute
2148  * Returns 1 if successful, 0 if not available or -1 on error
2149  */
libfsapfs_file_entry_get_utf16_symbolic_link_target_size(libfsapfs_file_entry_t * file_entry,size_t * utf16_string_size,libcerror_error_t ** error)2150 int libfsapfs_file_entry_get_utf16_symbolic_link_target_size(
2151      libfsapfs_file_entry_t *file_entry,
2152      size_t *utf16_string_size,
2153      libcerror_error_t **error )
2154 {
2155 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2156 	static char *function                                = "libfsapfs_file_entry_get_utf16_symbolic_link_target_size";
2157 	int result                                           = 0;
2158 
2159 	if( file_entry == NULL )
2160 	{
2161 		libcerror_error_set(
2162 		 error,
2163 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2164 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2165 		 "%s: invalid file entry.",
2166 		 function );
2167 
2168 		return( -1 );
2169 	}
2170 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2171 
2172 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2173 	if( libcthreads_read_write_lock_grab_for_write(
2174 	     internal_file_entry->read_write_lock,
2175 	     error ) != 1 )
2176 	{
2177 		libcerror_error_set(
2178 		 error,
2179 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2180 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2181 		 "%s: unable to grab read/write lock for writing.",
2182 		 function );
2183 
2184 		return( -1 );
2185 	}
2186 #endif
2187 	if( internal_file_entry->symbolic_link_data == NULL )
2188 	{
2189 		if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2190 		     internal_file_entry,
2191 		     error ) != 1 )
2192 		{
2193 			libcerror_error_set(
2194 			 error,
2195 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2196 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2197 			 "%s: unable to determine symbolic link data.",
2198 			 function );
2199 
2200 			goto on_error;
2201 		}
2202 	}
2203 	if( internal_file_entry->symbolic_link_data != NULL )
2204 	{
2205 		if( libuna_utf16_string_size_from_utf8_stream(
2206 		     internal_file_entry->symbolic_link_data,
2207 		     internal_file_entry->symbolic_link_data_size,
2208 		     utf16_string_size,
2209 		     error ) != 1 )
2210 		{
2211 			libcerror_error_set(
2212 			 error,
2213 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2214 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2215 			 "%s: unable to retrieve UTF-16 string size.",
2216 			 function );
2217 
2218 			goto on_error;
2219 		}
2220 		result = 1;
2221 	}
2222 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2223 	if( libcthreads_read_write_lock_release_for_write(
2224 	     internal_file_entry->read_write_lock,
2225 	     error ) != 1 )
2226 	{
2227 		libcerror_error_set(
2228 		 error,
2229 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2230 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2231 		 "%s: unable to release read/write lock for writing.",
2232 		 function );
2233 
2234 		return( -1 );
2235 	}
2236 #endif
2237 	return( result );
2238 
2239 on_error:
2240 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2241 	libcthreads_read_write_lock_release_for_write(
2242 	 internal_file_entry->read_write_lock,
2243 	 NULL );
2244 #endif
2245 	return( -1 );
2246 }
2247 
2248 /* Retrieves the UTF-16 encoded symbolic link target
2249  * The size should include the end of string character
2250  * This value is retrieved from the com.apple.fs.symlink extended attribute
2251  * Returns 1 if successful, 0 if not available or -1 on error
2252  */
libfsapfs_file_entry_get_utf16_symbolic_link_target(libfsapfs_file_entry_t * file_entry,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)2253 int libfsapfs_file_entry_get_utf16_symbolic_link_target(
2254      libfsapfs_file_entry_t *file_entry,
2255      uint16_t *utf16_string,
2256      size_t utf16_string_size,
2257      libcerror_error_t **error )
2258 {
2259 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2260 	static char *function                                = "libfsapfs_file_entry_get_utf16_symbolic_link_target";
2261 	int result                                           = 0;
2262 
2263 	if( file_entry == NULL )
2264 	{
2265 		libcerror_error_set(
2266 		 error,
2267 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2268 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2269 		 "%s: invalid file entry.",
2270 		 function );
2271 
2272 		return( -1 );
2273 	}
2274 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2275 
2276 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2277 	if( libcthreads_read_write_lock_grab_for_write(
2278 	     internal_file_entry->read_write_lock,
2279 	     error ) != 1 )
2280 	{
2281 		libcerror_error_set(
2282 		 error,
2283 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2284 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2285 		 "%s: unable to grab read/write lock for writing.",
2286 		 function );
2287 
2288 		return( -1 );
2289 	}
2290 #endif
2291 	if( internal_file_entry->symbolic_link_data == NULL )
2292 	{
2293 		if( libfsapfs_internal_file_entry_get_symbolic_link_data(
2294 		     internal_file_entry,
2295 		     error ) != 1 )
2296 		{
2297 			libcerror_error_set(
2298 			 error,
2299 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2300 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2301 			 "%s: unable to determine symbolic link data.",
2302 			 function );
2303 
2304 			goto on_error;
2305 		}
2306 	}
2307 	if( internal_file_entry->symbolic_link_data != NULL )
2308 	{
2309 		if( libuna_utf16_string_copy_from_utf8_stream(
2310 		     utf16_string,
2311 		     utf16_string_size,
2312 		     internal_file_entry->symbolic_link_data,
2313 		     internal_file_entry->symbolic_link_data_size,
2314 		     error ) != 1 )
2315 		{
2316 			libcerror_error_set(
2317 			 error,
2318 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2319 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2320 			 "%s: unable to retrieve UTF-16 string.",
2321 			 function );
2322 
2323 			goto on_error;
2324 		}
2325 		result = 1;
2326 	}
2327 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2328 	if( libcthreads_read_write_lock_release_for_write(
2329 	     internal_file_entry->read_write_lock,
2330 	     error ) != 1 )
2331 	{
2332 		libcerror_error_set(
2333 		 error,
2334 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2335 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2336 		 "%s: unable to release read/write lock for writing.",
2337 		 function );
2338 
2339 		return( -1 );
2340 	}
2341 #endif
2342 	return( result );
2343 
2344 on_error:
2345 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2346 	libcthreads_read_write_lock_release_for_write(
2347 	 internal_file_entry->read_write_lock,
2348 	 NULL );
2349 #endif
2350 	return( -1 );
2351 }
2352 
2353 /* Retrieves the number of extended attributes
2354  * Returns 1 if successful or -1 on error
2355  */
libfsapfs_file_entry_get_number_of_extended_attributes(libfsapfs_file_entry_t * file_entry,int * number_of_extended_attributes,libcerror_error_t ** error)2356 int libfsapfs_file_entry_get_number_of_extended_attributes(
2357      libfsapfs_file_entry_t *file_entry,
2358      int *number_of_extended_attributes,
2359      libcerror_error_t **error )
2360 {
2361 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2362 	static char *function                                = "libfsapfs_file_entry_get_number_of_extended_attributes";
2363 	int result                                           = 1;
2364 
2365 	if( file_entry == NULL )
2366 	{
2367 		libcerror_error_set(
2368 		 error,
2369 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2370 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2371 		 "%s: invalid file entry.",
2372 		 function );
2373 
2374 		return( -1 );
2375 	}
2376 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2377 
2378 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2379 	if( libcthreads_read_write_lock_grab_for_write(
2380 	     internal_file_entry->read_write_lock,
2381 	     error ) != 1 )
2382 	{
2383 		libcerror_error_set(
2384 		 error,
2385 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2386 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2387 		 "%s: unable to grab read/write lock for writing.",
2388 		 function );
2389 
2390 		return( -1 );
2391 	}
2392 #endif
2393 	if( internal_file_entry->extended_attributes == NULL )
2394 	{
2395 		if( libfsapfs_internal_file_entry_get_extended_attributes(
2396 		     internal_file_entry,
2397 		     error ) != 1 )
2398 		{
2399 			libcerror_error_set(
2400 			 error,
2401 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2402 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2403 			 "%s: unable to determine extended attributes.",
2404 			 function );
2405 
2406 			result = -1;
2407 		}
2408 	}
2409 	if( result != -1 )
2410 	{
2411 		if( libcdata_array_get_number_of_entries(
2412 		     internal_file_entry->extended_attributes,
2413 		     number_of_extended_attributes,
2414 		     error ) != 1 )
2415 		{
2416 			libcerror_error_set(
2417 			 error,
2418 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2419 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2420 			 "%s: unable to retrieve number of entries from extended attributes array.",
2421 			 function );
2422 
2423 			result = -1;
2424 		}
2425 	}
2426 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2427 	if( libcthreads_read_write_lock_release_for_write(
2428 	     internal_file_entry->read_write_lock,
2429 	     error ) != 1 )
2430 	{
2431 		libcerror_error_set(
2432 		 error,
2433 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2434 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2435 		 "%s: unable to release read/write lock for writing.",
2436 		 function );
2437 
2438 		return( -1 );
2439 	}
2440 #endif
2441 	return( result );
2442 }
2443 
2444 /* Retrieves the extended attribute for the specific index
2445  * Returns 1 if successful or -1 on error
2446  */
libfsapfs_file_entry_get_extended_attribute_by_index(libfsapfs_file_entry_t * file_entry,int extended_attribute_index,libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)2447 int libfsapfs_file_entry_get_extended_attribute_by_index(
2448      libfsapfs_file_entry_t *file_entry,
2449      int extended_attribute_index,
2450      libfsapfs_extended_attribute_t **extended_attribute,
2451      libcerror_error_t **error )
2452 {
2453 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2454 	static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_index";
2455 	int result                                           = 1;
2456 
2457 	if( file_entry == NULL )
2458 	{
2459 		libcerror_error_set(
2460 		 error,
2461 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2462 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2463 		 "%s: invalid file entry.",
2464 		 function );
2465 
2466 		return( -1 );
2467 	}
2468 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2469 
2470 	if( extended_attribute == NULL )
2471 	{
2472 		libcerror_error_set(
2473 		 error,
2474 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2475 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2476 		 "%s: invalid extended attribute.",
2477 		 function );
2478 
2479 		return( -1 );
2480 	}
2481 	if( *extended_attribute != NULL )
2482 	{
2483 		libcerror_error_set(
2484 		 error,
2485 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2486 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2487 		 "%s: invalid extended attribute value already set.",
2488 		 function );
2489 
2490 		return( -1 );
2491 	}
2492 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2493 	if( libcthreads_read_write_lock_grab_for_write(
2494 	     internal_file_entry->read_write_lock,
2495 	     error ) != 1 )
2496 	{
2497 		libcerror_error_set(
2498 		 error,
2499 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2500 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2501 		 "%s: unable to grab read/write lock for writing.",
2502 		 function );
2503 
2504 		return( -1 );
2505 	}
2506 #endif
2507 	if( internal_file_entry->extended_attributes == NULL )
2508 	{
2509 		if( libfsapfs_internal_file_entry_get_extended_attributes(
2510 		     internal_file_entry,
2511 		     error ) != 1 )
2512 		{
2513 			libcerror_error_set(
2514 			 error,
2515 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2516 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2517 			 "%s: unable to determine extended attributes.",
2518 			 function );
2519 
2520 			result = -1;
2521 		}
2522 	}
2523 	if( result != -1 )
2524 	{
2525 		if( libcdata_array_get_entry_by_index(
2526 		     internal_file_entry->extended_attributes,
2527 		     extended_attribute_index,
2528 		     (intptr_t **) extended_attribute,
2529 		     error ) != 1 )
2530 		{
2531 			libcerror_error_set(
2532 			 error,
2533 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2534 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2535 			 "%s: unable to retrieve extended attribute: %d.",
2536 			 function,
2537 			 extended_attribute_index );
2538 
2539 			result = -1;
2540 		}
2541 	}
2542 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2543 	if( libcthreads_read_write_lock_release_for_write(
2544 	     internal_file_entry->read_write_lock,
2545 	     error ) != 1 )
2546 	{
2547 		libcerror_error_set(
2548 		 error,
2549 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2550 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2551 		 "%s: unable to release read/write lock for writing.",
2552 		 function );
2553 
2554 		return( -1 );
2555 	}
2556 #endif
2557 	return( result );
2558 }
2559 
2560 /* Retrieves the extended attribute for an UTF-8 encoded name
2561  * Returns 1 if successful, 0 if no such file entry or -1 on error
2562  */
libfsapfs_internal_file_entry_get_extended_attribute_by_utf8_name(libfsapfs_internal_file_entry_t * internal_file_entry,const uint8_t * utf8_string,size_t utf8_string_length,libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)2563 int libfsapfs_internal_file_entry_get_extended_attribute_by_utf8_name(
2564      libfsapfs_internal_file_entry_t *internal_file_entry,
2565      const uint8_t *utf8_string,
2566      size_t utf8_string_length,
2567      libfsapfs_extended_attribute_t **extended_attribute,
2568      libcerror_error_t **error )
2569 {
2570 	libfsapfs_extended_attribute_t *safe_extended_attribute = NULL;
2571 	static char *function                                   = "libfsapfs_internal_file_entry_get_extended_attribute_by_utf8_name";
2572 	int extended_attribute_index                            = 0;
2573 	int number_of_extended_attributes                       = 0;
2574 	int result                                              = 0;
2575 
2576 	if( internal_file_entry == NULL )
2577 	{
2578 		libcerror_error_set(
2579 		 error,
2580 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2581 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2582 		 "%s: invalid file entry.",
2583 		 function );
2584 
2585 		return( -1 );
2586 	}
2587 	if( internal_file_entry->extended_attributes == NULL )
2588 	{
2589 		if( libfsapfs_internal_file_entry_get_extended_attributes(
2590 		     internal_file_entry,
2591 		     error ) != 1 )
2592 		{
2593 			libcerror_error_set(
2594 			 error,
2595 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2596 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2597 			 "%s: unable to determine extended attributes.",
2598 			 function );
2599 
2600 			return( -1 );
2601 		}
2602 	}
2603 	if( libcdata_array_get_number_of_entries(
2604 	     internal_file_entry->extended_attributes,
2605 	     &number_of_extended_attributes,
2606 	     error ) != 1 )
2607 	{
2608 		libcerror_error_set(
2609 		 error,
2610 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2611 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2612 		 "%s: unable to retrieve number of entries from extended attributes array.",
2613 		 function );
2614 
2615 		return( -1 );
2616 	}
2617 	for( extended_attribute_index = 0;
2618 	     extended_attribute_index < number_of_extended_attributes;
2619 	     extended_attribute_index++ )
2620 	{
2621 		if( libcdata_array_get_entry_by_index(
2622 		     internal_file_entry->extended_attributes,
2623 		     extended_attribute_index,
2624 		     (intptr_t **) &safe_extended_attribute,
2625 		     error ) != 1 )
2626 		{
2627 			libcerror_error_set(
2628 			 error,
2629 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2630 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2631 			 "%s: unable to retrieve extended attribute: %d.",
2632 			 function,
2633 			 extended_attribute_index );
2634 
2635 			return( -1 );
2636 		}
2637 		result = libfsapfs_extended_attribute_compare_name_with_utf8_string(
2638 		          safe_extended_attribute,
2639 		          utf8_string,
2640 		          utf8_string_length,
2641 		          error );
2642 
2643 		if( result == -1 )
2644 		{
2645 			libcerror_error_set(
2646 			 error,
2647 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2648 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2649 			 "%s: unable to compare UTF-8 string with name of extended attribute.",
2650 			 function );
2651 
2652 			return( -1 );
2653 		}
2654 		else if( result == LIBUNA_COMPARE_EQUAL )
2655 		{
2656 			*extended_attribute = safe_extended_attribute;
2657 
2658 			return( 1 );
2659 		}
2660 	}
2661 	return( 0 );
2662 }
2663 
2664 /* Retrieves the extended attribute for an UTF-16 encoded name
2665  * Returns 1 if successful, 0 if no such file entry or -1 on error
2666  */
libfsapfs_internal_file_entry_get_extended_attribute_by_utf16_name(libfsapfs_internal_file_entry_t * internal_file_entry,const uint16_t * utf16_string,size_t utf16_string_length,libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)2667 int libfsapfs_internal_file_entry_get_extended_attribute_by_utf16_name(
2668      libfsapfs_internal_file_entry_t *internal_file_entry,
2669      const uint16_t *utf16_string,
2670      size_t utf16_string_length,
2671      libfsapfs_extended_attribute_t **extended_attribute,
2672      libcerror_error_t **error )
2673 {
2674 	libfsapfs_extended_attribute_t *safe_extended_attribute = NULL;
2675 	static char *function                                   = "libfsapfs_internal_file_entry_get_extended_attribute_by_utf16_name";
2676 	int extended_attribute_index                            = 0;
2677 	int number_of_extended_attributes                       = 0;
2678 	int result                                              = 0;
2679 
2680 	if( internal_file_entry == NULL )
2681 	{
2682 		libcerror_error_set(
2683 		 error,
2684 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2685 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2686 		 "%s: invalid file entry.",
2687 		 function );
2688 
2689 		return( -1 );
2690 	}
2691 	if( internal_file_entry->extended_attributes == NULL )
2692 	{
2693 		if( libfsapfs_internal_file_entry_get_extended_attributes(
2694 		     internal_file_entry,
2695 		     error ) != 1 )
2696 		{
2697 			libcerror_error_set(
2698 			 error,
2699 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2700 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2701 			 "%s: unable to determine extended attributes.",
2702 			 function );
2703 
2704 			return( -1 );
2705 		}
2706 	}
2707 	if( libcdata_array_get_number_of_entries(
2708 	     internal_file_entry->extended_attributes,
2709 	     &number_of_extended_attributes,
2710 	     error ) != 1 )
2711 	{
2712 		libcerror_error_set(
2713 		 error,
2714 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2715 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2716 		 "%s: unable to retrieve number of entries from extended attributes array.",
2717 		 function );
2718 
2719 		return( -1 );
2720 	}
2721 	for( extended_attribute_index = 0;
2722 	     extended_attribute_index < number_of_extended_attributes;
2723 	     extended_attribute_index++ )
2724 	{
2725 		if( libcdata_array_get_entry_by_index(
2726 		     internal_file_entry->extended_attributes,
2727 		     extended_attribute_index,
2728 		     (intptr_t **) &safe_extended_attribute,
2729 		     error ) != 1 )
2730 		{
2731 			libcerror_error_set(
2732 			 error,
2733 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2734 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2735 			 "%s: unable to retrieve extended attribute: %d.",
2736 			 function,
2737 			 extended_attribute_index );
2738 
2739 			return( -1 );
2740 		}
2741 		result = libfsapfs_extended_attribute_compare_name_with_utf16_string(
2742 		          safe_extended_attribute,
2743 		          utf16_string,
2744 		          utf16_string_length,
2745 		          error );
2746 
2747 		if( result == -1 )
2748 		{
2749 			libcerror_error_set(
2750 			 error,
2751 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2752 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2753 			 "%s: unable to compare UTF-16 string with name of extended attribute.",
2754 			 function );
2755 
2756 			return( -1 );
2757 		}
2758 		else if( result == LIBUNA_COMPARE_EQUAL )
2759 		{
2760 			*extended_attribute = safe_extended_attribute;
2761 
2762 			return( 1 );
2763 		}
2764 	}
2765 	return( 0 );
2766 }
2767 
2768 /* Determines if there is an extended attribute for an UTF-8 encoded name
2769  * Returns 1 if available, 0 if not or -1 on error
2770  */
libfsapfs_file_entry_has_extended_attribute_by_utf8_name(libfsapfs_file_entry_t * file_entry,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)2771 int libfsapfs_file_entry_has_extended_attribute_by_utf8_name(
2772      libfsapfs_file_entry_t *file_entry,
2773      const uint8_t *utf8_string,
2774      size_t utf8_string_length,
2775      libcerror_error_t **error )
2776 {
2777 	libfsapfs_extended_attribute_t *extended_attribute   = NULL;
2778 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2779 	static char *function                                = "libfsapfs_file_entry_has_extended_attribute_by_utf8_name";
2780 	int result                                           = 0;
2781 
2782 	if( file_entry == NULL )
2783 	{
2784 		libcerror_error_set(
2785 		 error,
2786 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2787 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2788 		 "%s: invalid file entry.",
2789 		 function );
2790 
2791 		return( -1 );
2792 	}
2793 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2794 
2795 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2796 	if( libcthreads_read_write_lock_grab_for_write(
2797 	     internal_file_entry->read_write_lock,
2798 	     error ) != 1 )
2799 	{
2800 		libcerror_error_set(
2801 		 error,
2802 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2803 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2804 		 "%s: unable to grab read/write lock for writing.",
2805 		 function );
2806 
2807 		return( -1 );
2808 	}
2809 #endif
2810 	result = libfsapfs_internal_file_entry_get_extended_attribute_by_utf8_name(
2811 	          internal_file_entry,
2812 	          utf8_string,
2813 	          utf8_string_length,
2814 	          &extended_attribute,
2815 	          error );
2816 
2817 	if( result == -1 )
2818 	{
2819 		libcerror_error_set(
2820 		 error,
2821 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2822 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2823 		 "%s: unable to retrieve extended attribute for UTF-8 name.",
2824 		 function );
2825 
2826 		result = -1;
2827 	}
2828 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2829 	if( libcthreads_read_write_lock_release_for_write(
2830 	     internal_file_entry->read_write_lock,
2831 	     error ) != 1 )
2832 	{
2833 		libcerror_error_set(
2834 		 error,
2835 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2836 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2837 		 "%s: unable to release read/write lock for writing.",
2838 		 function );
2839 
2840 		return( -1 );
2841 	}
2842 #endif
2843 	return( result );
2844 }
2845 
2846 /* Determines if there is an extended attribute for an UTF-8 encoded name
2847  * Returns 1 if available, 0 if not or -1 on error
2848  */
libfsapfs_file_entry_has_extended_attribute_by_utf16_name(libfsapfs_file_entry_t * file_entry,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)2849 int libfsapfs_file_entry_has_extended_attribute_by_utf16_name(
2850      libfsapfs_file_entry_t *file_entry,
2851      const uint16_t *utf16_string,
2852      size_t utf16_string_length,
2853      libcerror_error_t **error )
2854 {
2855 	libfsapfs_extended_attribute_t *extended_attribute   = NULL;
2856 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2857 	static char *function                                = "libfsapfs_file_entry_has_extended_attribute_by_utf16_name";
2858 	int result                                           = 0;
2859 
2860 	if( file_entry == NULL )
2861 	{
2862 		libcerror_error_set(
2863 		 error,
2864 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2865 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2866 		 "%s: invalid file entry.",
2867 		 function );
2868 
2869 		return( -1 );
2870 	}
2871 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2872 
2873 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2874 	if( libcthreads_read_write_lock_grab_for_write(
2875 	     internal_file_entry->read_write_lock,
2876 	     error ) != 1 )
2877 	{
2878 		libcerror_error_set(
2879 		 error,
2880 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2881 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2882 		 "%s: unable to grab read/write lock for writing.",
2883 		 function );
2884 
2885 		return( -1 );
2886 	}
2887 #endif
2888 	result = libfsapfs_internal_file_entry_get_extended_attribute_by_utf16_name(
2889 	          internal_file_entry,
2890 	          utf16_string,
2891 	          utf16_string_length,
2892 	          &extended_attribute,
2893 	          error );
2894 
2895 	if( result == -1 )
2896 	{
2897 		libcerror_error_set(
2898 		 error,
2899 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2900 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2901 		 "%s: unable to retrieve extended attribute for UTF-16 name.",
2902 		 function );
2903 
2904 		result = -1;
2905 	}
2906 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2907 	if( libcthreads_read_write_lock_release_for_write(
2908 	     internal_file_entry->read_write_lock,
2909 	     error ) != 1 )
2910 	{
2911 		libcerror_error_set(
2912 		 error,
2913 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2914 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2915 		 "%s: unable to release read/write lock for writing.",
2916 		 function );
2917 
2918 		return( -1 );
2919 	}
2920 #endif
2921 	return( result );
2922 }
2923 
2924 /* Retrieves the extended attribute for an UTF-8 encoded name
2925  * Returns 1 if successful, 0 if no such file entry or -1 on error
2926  */
libfsapfs_file_entry_get_extended_attribute_by_utf8_name(libfsapfs_file_entry_t * file_entry,const uint8_t * utf8_string,size_t utf8_string_length,libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)2927 int libfsapfs_file_entry_get_extended_attribute_by_utf8_name(
2928      libfsapfs_file_entry_t *file_entry,
2929      const uint8_t *utf8_string,
2930      size_t utf8_string_length,
2931      libfsapfs_extended_attribute_t **extended_attribute,
2932      libcerror_error_t **error )
2933 {
2934 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
2935 	static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_utf8_name";
2936 	int result                                           = 0;
2937 
2938 	if( file_entry == NULL )
2939 	{
2940 		libcerror_error_set(
2941 		 error,
2942 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2943 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2944 		 "%s: invalid file entry.",
2945 		 function );
2946 
2947 		return( -1 );
2948 	}
2949 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
2950 
2951 	if( extended_attribute == NULL )
2952 	{
2953 		libcerror_error_set(
2954 		 error,
2955 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2956 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2957 		 "%s: invalid extended attribute.",
2958 		 function );
2959 
2960 		return( -1 );
2961 	}
2962 	if( *extended_attribute != NULL )
2963 	{
2964 		libcerror_error_set(
2965 		 error,
2966 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2967 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2968 		 "%s: invalid extended attribute value already set.",
2969 		 function );
2970 
2971 		return( -1 );
2972 	}
2973 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2974 	if( libcthreads_read_write_lock_grab_for_write(
2975 	     internal_file_entry->read_write_lock,
2976 	     error ) != 1 )
2977 	{
2978 		libcerror_error_set(
2979 		 error,
2980 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2981 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2982 		 "%s: unable to grab read/write lock for writing.",
2983 		 function );
2984 
2985 		return( -1 );
2986 	}
2987 #endif
2988 	result = libfsapfs_internal_file_entry_get_extended_attribute_by_utf8_name(
2989 	          internal_file_entry,
2990 	          utf8_string,
2991 	          utf8_string_length,
2992 	          extended_attribute,
2993 	          error );
2994 
2995 	if( result == -1 )
2996 	{
2997 		libcerror_error_set(
2998 		 error,
2999 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3000 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3001 		 "%s: unable to retrieve extended attribute for UTF-8 name.",
3002 		 function );
3003 
3004 		result = -1;
3005 	}
3006 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3007 	if( libcthreads_read_write_lock_release_for_write(
3008 	     internal_file_entry->read_write_lock,
3009 	     error ) != 1 )
3010 	{
3011 		libcerror_error_set(
3012 		 error,
3013 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3014 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3015 		 "%s: unable to release read/write lock for writing.",
3016 		 function );
3017 
3018 		return( -1 );
3019 	}
3020 #endif
3021 	return( result );
3022 }
3023 
3024 /* Retrieves the extended attribute for an UTF-16 encoded name
3025  * Returns 1 if successful, 0 if no such file entry or -1 on error
3026  */
libfsapfs_file_entry_get_extended_attribute_by_utf16_name(libfsapfs_file_entry_t * file_entry,const uint16_t * utf16_string,size_t utf16_string_length,libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)3027 int libfsapfs_file_entry_get_extended_attribute_by_utf16_name(
3028      libfsapfs_file_entry_t *file_entry,
3029      const uint16_t *utf16_string,
3030      size_t utf16_string_length,
3031      libfsapfs_extended_attribute_t **extended_attribute,
3032      libcerror_error_t **error )
3033 {
3034 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3035 	static char *function                                = "libfsapfs_file_entry_get_extended_attribute_by_utf16_name";
3036 	int result                                           = 0;
3037 
3038 	if( file_entry == NULL )
3039 	{
3040 		libcerror_error_set(
3041 		 error,
3042 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3043 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3044 		 "%s: invalid file entry.",
3045 		 function );
3046 
3047 		return( -1 );
3048 	}
3049 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3050 
3051 	if( extended_attribute == NULL )
3052 	{
3053 		libcerror_error_set(
3054 		 error,
3055 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3056 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3057 		 "%s: invalid extended attribute.",
3058 		 function );
3059 
3060 		return( -1 );
3061 	}
3062 	if( *extended_attribute != NULL )
3063 	{
3064 		libcerror_error_set(
3065 		 error,
3066 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3067 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3068 		 "%s: invalid extended attribute value already set.",
3069 		 function );
3070 
3071 		return( -1 );
3072 	}
3073 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3074 	if( libcthreads_read_write_lock_grab_for_write(
3075 	     internal_file_entry->read_write_lock,
3076 	     error ) != 1 )
3077 	{
3078 		libcerror_error_set(
3079 		 error,
3080 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3081 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3082 		 "%s: unable to grab read/write lock for writing.",
3083 		 function );
3084 
3085 		return( -1 );
3086 	}
3087 #endif
3088 	result = libfsapfs_internal_file_entry_get_extended_attribute_by_utf16_name(
3089 	          internal_file_entry,
3090 	          utf16_string,
3091 	          utf16_string_length,
3092 	          extended_attribute,
3093 	          error );
3094 
3095 	if( result == -1 )
3096 	{
3097 		libcerror_error_set(
3098 		 error,
3099 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3100 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3101 		 "%s: unable to retrieve extended attribute for UTF-16 name.",
3102 		 function );
3103 
3104 		result = -1;
3105 	}
3106 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3107 	if( libcthreads_read_write_lock_release_for_write(
3108 	     internal_file_entry->read_write_lock,
3109 	     error ) != 1 )
3110 	{
3111 		libcerror_error_set(
3112 		 error,
3113 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3114 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3115 		 "%s: unable to release read/write lock for writing.",
3116 		 function );
3117 
3118 		return( -1 );
3119 	}
3120 #endif
3121 	return( result );
3122 }
3123 
3124 /* Determines the directory entries
3125  * Returns 1 if successful or -1 on error
3126  */
libfsapfs_internal_file_entry_get_directory_entries(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)3127 int libfsapfs_internal_file_entry_get_directory_entries(
3128      libfsapfs_internal_file_entry_t *internal_file_entry,
3129      libcerror_error_t **error )
3130 {
3131 	static char *function           = "libfsapfs_internal_file_entry_get_directory_entries";
3132 	uint64_t file_system_identifier = 0;
3133 	int result                      = 0;
3134 
3135 	if( internal_file_entry == NULL )
3136 	{
3137 		libcerror_error_set(
3138 		 error,
3139 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3140 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3141 		 "%s: invalid file entry.",
3142 		 function );
3143 
3144 		return( -1 );
3145 	}
3146 	if( internal_file_entry->directory_entries != NULL )
3147 	{
3148 		libcerror_error_set(
3149 		 error,
3150 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3151 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3152 		 "%s: invalid file entry - directory entries value already set.",
3153 		 function );
3154 
3155 		return( -1 );
3156 	}
3157 	if( libfsapfs_inode_get_identifier(
3158 	     internal_file_entry->inode,
3159 	     &file_system_identifier,
3160 	     error ) != 1 )
3161 	{
3162 		libcerror_error_set(
3163 		 error,
3164 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3165 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3166 		 "%s: unable to retrieve identifier from inode.",
3167 		 function );
3168 
3169 		goto on_error;
3170 	}
3171 	if( libcdata_array_initialize(
3172 	     &( internal_file_entry->directory_entries ),
3173 	     0,
3174 	     error ) != 1 )
3175 	{
3176 		libcerror_error_set(
3177 		 error,
3178 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3179 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3180 		 "%s: unable to create directory entries array.",
3181 		 function );
3182 
3183 		goto on_error;
3184 	}
3185 	result = libfsapfs_file_system_btree_get_directory_entries(
3186 		  internal_file_entry->file_system_btree,
3187 		  internal_file_entry->file_io_handle,
3188 		  file_system_identifier,
3189 		  internal_file_entry->directory_entries,
3190 		  error );
3191 
3192 	if( result == -1 )
3193 	{
3194 		libcerror_error_set(
3195 		 error,
3196 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3197 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3198 		 "%s: unable to retrieve directory entries from file system B-tree.",
3199 		 function );
3200 
3201 		goto on_error;
3202 	}
3203 	return( 1 );
3204 
3205 on_error:
3206 	if( internal_file_entry->directory_entries != NULL )
3207 	{
3208 		libcdata_array_free(
3209 		 &( internal_file_entry->directory_entries ),
3210 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_directory_record_free,
3211 		 NULL );
3212 	}
3213 	return( -1 );
3214 }
3215 
3216 /* Retrieves the number of sub file entries
3217  * Returns 1 if successful or -1 on error
3218  */
libfsapfs_file_entry_get_number_of_sub_file_entries(libfsapfs_file_entry_t * file_entry,int * number_of_sub_file_entries,libcerror_error_t ** error)3219 int libfsapfs_file_entry_get_number_of_sub_file_entries(
3220      libfsapfs_file_entry_t *file_entry,
3221      int *number_of_sub_file_entries,
3222      libcerror_error_t **error )
3223 {
3224 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3225 	static char *function                                = "libfsapfs_file_entry_get_number_of_sub_file_entries";
3226 	int result                                           = 1;
3227 
3228 	if( file_entry == NULL )
3229 	{
3230 		libcerror_error_set(
3231 		 error,
3232 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3233 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3234 		 "%s: invalid file entry.",
3235 		 function );
3236 
3237 		return( -1 );
3238 	}
3239 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3240 
3241 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3242 	if( libcthreads_read_write_lock_grab_for_write(
3243 	     internal_file_entry->read_write_lock,
3244 	     error ) != 1 )
3245 	{
3246 		libcerror_error_set(
3247 		 error,
3248 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3249 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3250 		 "%s: unable to grab read/write lock for writing.",
3251 		 function );
3252 
3253 		return( -1 );
3254 	}
3255 #endif
3256 	if( internal_file_entry->directory_entries == NULL )
3257 	{
3258 		if( libfsapfs_internal_file_entry_get_directory_entries(
3259 		     internal_file_entry,
3260 		     error ) != 1 )
3261 		{
3262 			libcerror_error_set(
3263 			 error,
3264 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3265 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3266 			 "%s: unable to determine directory entries.",
3267 			 function );
3268 
3269 			result = -1;
3270 		}
3271 	}
3272 	if( result != -1 )
3273 	{
3274 		if( libcdata_array_get_number_of_entries(
3275 		     internal_file_entry->directory_entries,
3276 		     number_of_sub_file_entries,
3277 		     error ) != 1 )
3278 		{
3279 			libcerror_error_set(
3280 			 error,
3281 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3282 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3283 			 "%s: unable to retrieve number of entries from array.",
3284 			 function );
3285 
3286 			result = -1;
3287 		}
3288 	}
3289 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3290 	if( libcthreads_read_write_lock_release_for_write(
3291 	     internal_file_entry->read_write_lock,
3292 	     error ) != 1 )
3293 	{
3294 		libcerror_error_set(
3295 		 error,
3296 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3297 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3298 		 "%s: unable to release read/write lock for writing.",
3299 		 function );
3300 
3301 		return( -1 );
3302 	}
3303 #endif
3304 	return( result );
3305 }
3306 
3307 /* Retrieves the sub file entry for the specific index
3308  * Returns 1 if successful or -1 on error
3309  */
libfsapfs_file_entry_get_sub_file_entry_by_index(libfsapfs_file_entry_t * file_entry,int sub_file_entry_index,libfsapfs_file_entry_t ** sub_file_entry,libcerror_error_t ** error)3310 int libfsapfs_file_entry_get_sub_file_entry_by_index(
3311      libfsapfs_file_entry_t *file_entry,
3312      int sub_file_entry_index,
3313      libfsapfs_file_entry_t **sub_file_entry,
3314      libcerror_error_t **error )
3315 {
3316 	libfsapfs_directory_record_t *directory_record       = NULL;
3317 	libfsapfs_directory_record_t *directory_record_copy  = NULL;
3318 	libfsapfs_inode_t *inode                             = NULL;
3319 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3320 	static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_index";
3321 	uint64_t file_system_identifier                      = 0;
3322 
3323 	if( file_entry == NULL )
3324 	{
3325 		libcerror_error_set(
3326 		 error,
3327 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3328 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3329 		 "%s: invalid file entry.",
3330 		 function );
3331 
3332 		return( -1 );
3333 	}
3334 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3335 
3336 	if( sub_file_entry == NULL )
3337 	{
3338 		libcerror_error_set(
3339 		 error,
3340 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3341 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3342 		 "%s: invalid sub file entry.",
3343 		 function );
3344 
3345 		return( -1 );
3346 	}
3347 	if( *sub_file_entry != NULL )
3348 	{
3349 		libcerror_error_set(
3350 		 error,
3351 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3352 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3353 		 "%s: invalid sub file entry value already set.",
3354 		 function );
3355 
3356 		return( -1 );
3357 	}
3358 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3359 	if( libcthreads_read_write_lock_grab_for_write(
3360 	     internal_file_entry->read_write_lock,
3361 	     error ) != 1 )
3362 	{
3363 		libcerror_error_set(
3364 		 error,
3365 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3366 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3367 		 "%s: unable to grab read/write lock for writing.",
3368 		 function );
3369 
3370 		return( -1 );
3371 	}
3372 #endif
3373 	if( internal_file_entry->directory_entries == NULL )
3374 	{
3375 		if( libfsapfs_internal_file_entry_get_directory_entries(
3376 		     internal_file_entry,
3377 		     error ) != 1 )
3378 		{
3379 			libcerror_error_set(
3380 			 error,
3381 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3382 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3383 			 "%s: unable to determine directory entries.",
3384 			 function );
3385 
3386 			goto on_error;
3387 		}
3388 	}
3389 	if( libcdata_array_get_entry_by_index(
3390 	     internal_file_entry->directory_entries,
3391 	     sub_file_entry_index,
3392 	     (intptr_t **) &directory_record,
3393 	     error ) != 1 )
3394 	{
3395 		libcerror_error_set(
3396 		 error,
3397 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3398 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3399 		 "%s: unable to retrieve directory entry: %d.",
3400 		 function,
3401 		 sub_file_entry_index );
3402 
3403 		goto on_error;
3404 	}
3405 	if( libfsapfs_directory_record_get_identifier(
3406 	     directory_record,
3407 	     &file_system_identifier,
3408 	     error ) != 1 )
3409 	{
3410 		libcerror_error_set(
3411 		 error,
3412 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3413 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3414 		 "%s: unable to retrieve file system identifier from directory entry: %d.",
3415 		 function,
3416 		 sub_file_entry_index );
3417 
3418 		goto on_error;
3419 	}
3420 	if( libfsapfs_file_system_btree_get_inode_by_identifier(
3421 	     internal_file_entry->file_system_btree,
3422 	     internal_file_entry->file_io_handle,
3423 	     file_system_identifier,
3424 	     &inode,
3425 	     error ) != 1 )
3426 	{
3427 		libcerror_error_set(
3428 		 error,
3429 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3430 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3431 		 "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
3432 		 function,
3433 		 file_system_identifier );
3434 
3435 		 goto on_error;
3436 	}
3437 	if( libfsapfs_directory_record_clone(
3438 	     &directory_record_copy,
3439 	     directory_record,
3440 	     error ) != 1 )
3441 	{
3442 		libcerror_error_set(
3443 		 error,
3444 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3445 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3446 		 "%s: unable to create directory record copy.",
3447 		 function );
3448 
3449 		goto on_error;
3450 	}
3451 	if( libfsapfs_file_entry_initialize(
3452 	     sub_file_entry,
3453 	     internal_file_entry->io_handle,
3454 	     internal_file_entry->file_io_handle,
3455 	     internal_file_entry->encryption_context,
3456 	     internal_file_entry->file_system_btree,
3457 	     inode,
3458 	     directory_record_copy,
3459 	     error ) != 1 )
3460 	{
3461 		libcerror_error_set(
3462 		 error,
3463 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3464 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3465 		 "%s: unable to create file entry.",
3466 		 function );
3467 
3468 		goto on_error;
3469 	}
3470 	inode                 = NULL;
3471 	directory_record_copy = NULL;
3472 
3473 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3474 	if( libcthreads_read_write_lock_release_for_write(
3475 	     internal_file_entry->read_write_lock,
3476 	     error ) != 1 )
3477 	{
3478 		libcerror_error_set(
3479 		 error,
3480 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3481 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3482 		 "%s: unable to release read/write lock for writing.",
3483 		 function );
3484 
3485 		return( -1 );
3486 	}
3487 #endif
3488 	return( 1 );
3489 
3490 on_error:
3491 	if( directory_record_copy != NULL )
3492 	{
3493 		libfsapfs_directory_record_free(
3494 		 &directory_record_copy,
3495 		 NULL );
3496 	}
3497 	if( inode != NULL )
3498 	{
3499 		libfsapfs_inode_free(
3500 		 &inode,
3501 		 NULL );
3502 	}
3503 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3504 	libcthreads_read_write_lock_release_for_write(
3505 	 internal_file_entry->read_write_lock,
3506 	 NULL );
3507 #endif
3508 	return( -1 );
3509 }
3510 
3511 /* Retrieves the sub file entry for an UTF-8 encoded name
3512  * Returns 1 if successful, 0 if no such file entry or -1 on error
3513  */
libfsapfs_file_entry_get_sub_file_entry_by_utf8_name(libfsapfs_file_entry_t * file_entry,const uint8_t * utf8_string,size_t utf8_string_length,libfsapfs_file_entry_t ** sub_file_entry,libcerror_error_t ** error)3514 int libfsapfs_file_entry_get_sub_file_entry_by_utf8_name(
3515      libfsapfs_file_entry_t *file_entry,
3516      const uint8_t *utf8_string,
3517      size_t utf8_string_length,
3518      libfsapfs_file_entry_t **sub_file_entry,
3519      libcerror_error_t **error )
3520 {
3521 	libfsapfs_directory_record_t *directory_record       = NULL;
3522 	libfsapfs_inode_t *inode                             = NULL;
3523 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3524 	static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_utf8_name";
3525 	uint64_t file_system_identifier                      = 0;
3526 	int result                                           = 0;
3527 
3528 	if( file_entry == NULL )
3529 	{
3530 		libcerror_error_set(
3531 		 error,
3532 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3533 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3534 		 "%s: invalid file entry.",
3535 		 function );
3536 
3537 		return( -1 );
3538 	}
3539 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3540 
3541 	if( sub_file_entry == NULL )
3542 	{
3543 		libcerror_error_set(
3544 		 error,
3545 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3546 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3547 		 "%s: invalid sub file entry.",
3548 		 function );
3549 
3550 		return( -1 );
3551 	}
3552 	if( *sub_file_entry != NULL )
3553 	{
3554 		libcerror_error_set(
3555 		 error,
3556 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3557 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3558 		 "%s: invalid sub file entry value already set.",
3559 		 function );
3560 
3561 		return( -1 );
3562 	}
3563 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3564 	if( libcthreads_read_write_lock_grab_for_write(
3565 	     internal_file_entry->read_write_lock,
3566 	     error ) != 1 )
3567 	{
3568 		libcerror_error_set(
3569 		 error,
3570 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3571 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3572 		 "%s: unable to grab read/write lock for writing.",
3573 		 function );
3574 
3575 		return( -1 );
3576 	}
3577 #endif
3578 	if( libfsapfs_inode_get_identifier(
3579 	     internal_file_entry->inode,
3580 	     &file_system_identifier,
3581 	     error ) != 1 )
3582 	{
3583 		libcerror_error_set(
3584 		 error,
3585 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3586 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3587 		 "%s: unable to retrieve identifier.",
3588 		 function );
3589 
3590 		goto on_error;
3591 	}
3592 	result = libfsapfs_file_system_btree_get_inode_by_utf8_path(
3593 	          internal_file_entry->file_system_btree,
3594 	          internal_file_entry->file_io_handle,
3595 	          file_system_identifier,
3596 	          utf8_string,
3597 	          utf8_string_length,
3598 	          &inode,
3599 	          &directory_record,
3600 	          error );
3601 
3602 	if( result == -1 )
3603 	{
3604 		libcerror_error_set(
3605 		 error,
3606 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3607 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3608 		 "%s: unable to retrieve inode from file system B-tree.",
3609 		 function );
3610 
3611 		goto on_error;
3612 	}
3613 	else if( result != 0 )
3614 	{
3615 		if( libfsapfs_file_entry_initialize(
3616 		     sub_file_entry,
3617 		     internal_file_entry->io_handle,
3618 		     internal_file_entry->file_io_handle,
3619 		     internal_file_entry->encryption_context,
3620 		     internal_file_entry->file_system_btree,
3621 		     inode,
3622 		     directory_record,
3623 		     error ) != 1 )
3624 		{
3625 			libcerror_error_set(
3626 			 error,
3627 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3628 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3629 			 "%s: unable to create sub file entry.",
3630 			 function );
3631 
3632 			goto on_error;
3633 		}
3634 	}
3635 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3636 	if( libcthreads_read_write_lock_release_for_write(
3637 	     internal_file_entry->read_write_lock,
3638 	     error ) != 1 )
3639 	{
3640 		libcerror_error_set(
3641 		 error,
3642 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3643 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3644 		 "%s: unable to release read/write lock for writing.",
3645 		 function );
3646 
3647 		return( -1 );
3648 	}
3649 #endif
3650 	return( result );
3651 
3652 on_error:
3653 	if( directory_record != NULL )
3654 	{
3655 		libfsapfs_directory_record_free(
3656 		 &directory_record,
3657 		 NULL );
3658 	}
3659 	if( inode != NULL )
3660 	{
3661 		libfsapfs_inode_free(
3662 		 &inode,
3663 		 NULL );
3664 	}
3665 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3666 	libcthreads_read_write_lock_release_for_write(
3667 	 internal_file_entry->read_write_lock,
3668 	 NULL );
3669 #endif
3670 	return( -1 );
3671 }
3672 
3673 /* Retrieves the sub file entry for an UTF-16 encoded name
3674  * Returns 1 if successful, 0 if no such file entry or -1 on error
3675  */
libfsapfs_file_entry_get_sub_file_entry_by_utf16_name(libfsapfs_file_entry_t * file_entry,const uint16_t * utf16_string,size_t utf16_string_length,libfsapfs_file_entry_t ** sub_file_entry,libcerror_error_t ** error)3676 int libfsapfs_file_entry_get_sub_file_entry_by_utf16_name(
3677      libfsapfs_file_entry_t *file_entry,
3678      const uint16_t *utf16_string,
3679      size_t utf16_string_length,
3680      libfsapfs_file_entry_t **sub_file_entry,
3681      libcerror_error_t **error )
3682 {
3683 	libfsapfs_directory_record_t *directory_record       = NULL;
3684 	libfsapfs_inode_t *inode                             = NULL;
3685 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
3686 	static char *function                                = "libfsapfs_file_entry_get_sub_file_entry_by_utf16_name";
3687 	uint64_t file_system_identifier                      = 0;
3688 	int result                                           = 0;
3689 
3690 	if( file_entry == NULL )
3691 	{
3692 		libcerror_error_set(
3693 		 error,
3694 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3695 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3696 		 "%s: invalid file entry.",
3697 		 function );
3698 
3699 		return( -1 );
3700 	}
3701 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
3702 
3703 	if( sub_file_entry == NULL )
3704 	{
3705 		libcerror_error_set(
3706 		 error,
3707 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3708 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3709 		 "%s: invalid sub file entry.",
3710 		 function );
3711 
3712 		return( -1 );
3713 	}
3714 	if( *sub_file_entry != NULL )
3715 	{
3716 		libcerror_error_set(
3717 		 error,
3718 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3719 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3720 		 "%s: invalid sub file entry value already set.",
3721 		 function );
3722 
3723 		return( -1 );
3724 	}
3725 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3726 	if( libcthreads_read_write_lock_grab_for_write(
3727 	     internal_file_entry->read_write_lock,
3728 	     error ) != 1 )
3729 	{
3730 		libcerror_error_set(
3731 		 error,
3732 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3733 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3734 		 "%s: unable to grab read/write lock for writing.",
3735 		 function );
3736 
3737 		return( -1 );
3738 	}
3739 #endif
3740 	if( libfsapfs_inode_get_identifier(
3741 	     internal_file_entry->inode,
3742 	     &file_system_identifier,
3743 	     error ) != 1 )
3744 	{
3745 		libcerror_error_set(
3746 		 error,
3747 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3748 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3749 		 "%s: unable to retrieve identifier.",
3750 		 function );
3751 
3752 		goto on_error;
3753 	}
3754 	result = libfsapfs_file_system_btree_get_inode_by_utf16_path(
3755 	          internal_file_entry->file_system_btree,
3756 	          internal_file_entry->file_io_handle,
3757 	          file_system_identifier,
3758 	          utf16_string,
3759 	          utf16_string_length,
3760 	          &inode,
3761 	          &directory_record,
3762 	          error );
3763 
3764 	if( result == -1 )
3765 	{
3766 		libcerror_error_set(
3767 		 error,
3768 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3769 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3770 		 "%s: unable to retrieve inode from file system B-tree.",
3771 		 function );
3772 
3773 		goto on_error;
3774 	}
3775 	else if( result != 0 )
3776 	{
3777 		if( libfsapfs_file_entry_initialize(
3778 		     sub_file_entry,
3779 		     internal_file_entry->io_handle,
3780 		     internal_file_entry->file_io_handle,
3781 		     internal_file_entry->encryption_context,
3782 		     internal_file_entry->file_system_btree,
3783 		     inode,
3784 		     directory_record,
3785 		     error ) != 1 )
3786 		{
3787 			libcerror_error_set(
3788 			 error,
3789 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3790 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3791 			 "%s: unable to create sub file entry.",
3792 			 function );
3793 
3794 			goto on_error;
3795 		}
3796 	}
3797 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3798 	if( libcthreads_read_write_lock_release_for_write(
3799 	     internal_file_entry->read_write_lock,
3800 	     error ) != 1 )
3801 	{
3802 		libcerror_error_set(
3803 		 error,
3804 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3805 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3806 		 "%s: unable to release read/write lock for writing.",
3807 		 function );
3808 
3809 		return( -1 );
3810 	}
3811 #endif
3812 	return( result );
3813 
3814 on_error:
3815 	if( directory_record != NULL )
3816 	{
3817 		libfsapfs_directory_record_free(
3818 		 &directory_record,
3819 		 NULL );
3820 	}
3821 	if( inode != NULL )
3822 	{
3823 		libfsapfs_inode_free(
3824 		 &inode,
3825 		 NULL );
3826 	}
3827 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3828 	libcthreads_read_write_lock_release_for_write(
3829 	 internal_file_entry->read_write_lock,
3830 	 NULL );
3831 #endif
3832 	return( -1 );
3833 }
3834 
3835 /* Determines the file extents
3836  * Returns 1 if successful or -1 on error
3837  */
libfsapfs_internal_file_entry_get_file_extents(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)3838 int libfsapfs_internal_file_entry_get_file_extents(
3839      libfsapfs_internal_file_entry_t *internal_file_entry,
3840      libcerror_error_t **error )
3841 {
3842 	static char *function           = "libfsapfs_internal_file_entry_get_file_extents";
3843 	uint64_t file_system_identifier = 0;
3844 	int result                      = 0;
3845 
3846 	if( internal_file_entry == NULL )
3847 	{
3848 		libcerror_error_set(
3849 		 error,
3850 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3851 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3852 		 "%s: invalid file entry.",
3853 		 function );
3854 
3855 		return( -1 );
3856 	}
3857 	if( internal_file_entry->file_extents != NULL )
3858 	{
3859 		libcerror_error_set(
3860 		 error,
3861 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3862 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3863 		 "%s: invalid file entry - file extents value already set.",
3864 		 function );
3865 
3866 		return( -1 );
3867 	}
3868 	if( libfsapfs_inode_get_data_stream_identifier(
3869 	     internal_file_entry->inode,
3870 	     &file_system_identifier,
3871 	     error ) != 1 )
3872 	{
3873 		libcerror_error_set(
3874 		 error,
3875 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3876 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3877 		 "%s: unable to retrieve data stream identifier from inode.",
3878 		 function );
3879 
3880 		goto on_error;
3881 	}
3882 	if( libcdata_array_initialize(
3883 	     &( internal_file_entry->file_extents ),
3884 	     0,
3885 	     error ) != 1 )
3886 	{
3887 		libcerror_error_set(
3888 		 error,
3889 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3890 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3891 		 "%s: unable to create file extents array.",
3892 		 function );
3893 
3894 		goto on_error;
3895 	}
3896 	result = libfsapfs_file_system_btree_get_file_extents(
3897 		  internal_file_entry->file_system_btree,
3898 		  internal_file_entry->file_io_handle,
3899 		  file_system_identifier,
3900 		  internal_file_entry->file_extents,
3901 		  error );
3902 
3903 	if( result == -1 )
3904 	{
3905 		libcerror_error_set(
3906 		 error,
3907 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3908 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3909 		 "%s: unable to retrieve file extents from file system B-tree.",
3910 		 function );
3911 
3912 		goto on_error;
3913 	}
3914 	return( 1 );
3915 
3916 on_error:
3917 	if( internal_file_entry->file_extents != NULL )
3918 	{
3919 		libcdata_array_free(
3920 		 &( internal_file_entry->file_extents ),
3921 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
3922 		 NULL );
3923 	}
3924 	return( -1 );
3925 }
3926 
3927 /* Determines the data stream
3928  * Returns 1 if successful or -1 on error
3929  */
libfsapfs_internal_file_entry_get_data_stream(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)3930 int libfsapfs_internal_file_entry_get_data_stream(
3931      libfsapfs_internal_file_entry_t *internal_file_entry,
3932      libcerror_error_t **error )
3933 {
3934 	libfdata_stream_t *compressed_data_stream = NULL;
3935 	static char *function                     = "libfsapfs_internal_file_entry_get_data_stream";
3936 	uint64_t data_stream_size                 = 0;
3937 	uint64_t inode_flags                      = 0;
3938 	uint8_t is_sparse                         = 0;
3939 	int compression_method                    = 0;
3940 
3941 	if( internal_file_entry == NULL )
3942 	{
3943 		libcerror_error_set(
3944 		 error,
3945 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3946 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3947 		 "%s: invalid file entry.",
3948 		 function );
3949 
3950 		return( -1 );
3951 	}
3952 	if( internal_file_entry->io_handle == NULL )
3953 	{
3954 		libcerror_error_set(
3955 		 error,
3956 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3957 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3958 		 "%s: invalid internal file entry - missing IO handle.",
3959 		 function );
3960 
3961 		return( -1 );
3962 	}
3963 	if( internal_file_entry->data_stream != NULL )
3964 	{
3965 		libcerror_error_set(
3966 		 error,
3967 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3968 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3969 		 "%s: invalid file entry - data stream value already set.",
3970 		 function );
3971 
3972 		return( -1 );
3973 	}
3974 	if( internal_file_entry->data_size == (size64_t) -1 )
3975 	{
3976 		if( libfsapfs_internal_file_entry_get_data_size(
3977 		     internal_file_entry,
3978 		     error ) != 1 )
3979 		{
3980 			libcerror_error_set(
3981 			 error,
3982 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3983 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3984 			 "%s: unable to determine data size.",
3985 			 function );
3986 
3987 			goto on_error;
3988 		}
3989 	}
3990 	if( internal_file_entry->compressed_data_header != NULL )
3991 	{
3992 		switch( internal_file_entry->compressed_data_header->compression_method )
3993 		{
3994 			case 3:
3995 			case 4:
3996 				compression_method = LIBFSAPFS_COMPRESSION_METHOD_DEFLATE;
3997 				break;
3998 
3999 			case 5:
4000 				compression_method = LIBFSAPFS_COMPRESSION_METHOD_UNKNOWN5;
4001 				break;
4002 
4003 			case 7:
4004 			case 8:
4005 				compression_method = LIBFSAPFS_COMPRESSION_METHOD_LZVN;
4006 				break;
4007 
4008 			default:
4009 				libcerror_error_set(
4010 				 error,
4011 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4012 				 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
4013 				 "%s: unsupported compression method: %d.",
4014 				 function,
4015 				 internal_file_entry->compressed_data_header->compression_method );
4016 
4017 				goto on_error;
4018 		}
4019 		if( ( internal_file_entry->compressed_data_header->compression_method == 4 )
4020 		 || ( internal_file_entry->compressed_data_header->compression_method == 8 ) )
4021 		{
4022 			if( libfsapfs_extended_attribute_get_data_stream(
4023 			     internal_file_entry->resource_fork_extended_attribute,
4024 			     &compressed_data_stream,
4025 			     error ) != 1 )
4026 			{
4027 				libcerror_error_set(
4028 				 error,
4029 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4030 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4031 				 "%s: unable to retrieve data stream from resource fork extended attribute.",
4032 				 function );
4033 
4034 				goto on_error;
4035 			}
4036 		}
4037 		else
4038 		{
4039 			if( libfsapfs_extended_attribute_get_data_stream(
4040 			     internal_file_entry->compressed_data_extended_attribute,
4041 			     &compressed_data_stream,
4042 			     error ) != 1 )
4043 			{
4044 				libcerror_error_set(
4045 				 error,
4046 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4047 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4048 				 "%s: unable to retrieve data stream from compressed data extended attribute.",
4049 				 function );
4050 
4051 				goto on_error;
4052 			}
4053 		}
4054 		if( libfsapfs_data_stream_initialize_from_compressed_data_stream(
4055 		     &( internal_file_entry->data_stream ),
4056 		     compressed_data_stream,
4057 		     internal_file_entry->data_size,
4058 		     compression_method,
4059 		     error ) != 1 )
4060 		{
4061 			libcerror_error_set(
4062 			 error,
4063 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4064 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4065 			 "%s: unable to create data stream from compressed data stream.",
4066 			 function );
4067 
4068 			goto on_error;
4069 		}
4070 	}
4071 	else
4072 	{
4073 		if( internal_file_entry->file_extents == NULL )
4074 		{
4075 			if( libfsapfs_internal_file_entry_get_file_extents(
4076 			     internal_file_entry,
4077 			     error ) != 1 )
4078 			{
4079 				libcerror_error_set(
4080 				 error,
4081 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4082 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4083 				 "%s: unable to determine file extents.",
4084 				 function );
4085 
4086 				goto on_error;
4087 			}
4088 		}
4089 		if( libfsapfs_inode_get_flags(
4090 		     internal_file_entry->inode,
4091 		     &inode_flags,
4092 		     error ) != 1 )
4093 		{
4094 			libcerror_error_set(
4095 			 error,
4096 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4097 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4098 			 "%s: unable to retrieve flags from inode.",
4099 			 function );
4100 
4101 			goto on_error;
4102 		}
4103 		if( libfsapfs_inode_get_data_stream_size(
4104 		     internal_file_entry->inode,
4105 		     &data_stream_size,
4106 		     error ) != 1 )
4107 		{
4108 			libcerror_error_set(
4109 			 error,
4110 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4111 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4112 			 "%s: unable to retrieve data stream size from inode.",
4113 			 function );
4114 
4115 			goto on_error;
4116 		}
4117 		is_sparse = (uint8_t) ( ( inode_flags & 0x00000200 ) != 0 );
4118 
4119 		if( libfsapfs_data_stream_initialize_from_file_extents(
4120 		     &( internal_file_entry->data_stream ),
4121 		     internal_file_entry->io_handle,
4122 		     internal_file_entry->encryption_context,
4123 		     internal_file_entry->file_extents,
4124 		     (size64_t) data_stream_size,
4125 		     is_sparse,
4126 		     error ) != 1 )
4127 		{
4128 			libcerror_error_set(
4129 			 error,
4130 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4131 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4132 			 "%s: unable to create data stream from file extents.",
4133 			 function );
4134 
4135 			goto on_error;
4136 		}
4137 	}
4138 	return( 1 );
4139 
4140 on_error:
4141 	if( internal_file_entry->data_stream != NULL )
4142 	{
4143 		libfdata_stream_free(
4144 		 &( internal_file_entry->data_stream ),
4145 		 NULL );
4146 	}
4147 	return( -1 );
4148 }
4149 
4150 /* Reads data at the current offset into a buffer
4151  * Returns the number of bytes read or -1 on error
4152  */
libfsapfs_file_entry_read_buffer(libfsapfs_file_entry_t * file_entry,void * buffer,size_t buffer_size,libcerror_error_t ** error)4153 ssize_t libfsapfs_file_entry_read_buffer(
4154          libfsapfs_file_entry_t *file_entry,
4155          void *buffer,
4156          size_t buffer_size,
4157          libcerror_error_t **error )
4158 {
4159 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4160 	static char *function                                = "libfsapfs_file_entry_read_buffer";
4161 	ssize_t read_count                                   = 0;
4162 
4163 	if( file_entry == NULL )
4164 	{
4165 		libcerror_error_set(
4166 		 error,
4167 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4168 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4169 		 "%s: invalid file entry.",
4170 		 function );
4171 
4172 		return( -1 );
4173 	}
4174 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4175 
4176 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4177 	if( libcthreads_read_write_lock_grab_for_write(
4178 	     internal_file_entry->read_write_lock,
4179 	     error ) != 1 )
4180 	{
4181 		libcerror_error_set(
4182 		 error,
4183 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4184 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4185 		 "%s: unable to grab read/write lock for writing.",
4186 		 function );
4187 
4188 		return( -1 );
4189 	}
4190 #endif
4191 	if( internal_file_entry->data_stream == NULL )
4192 	{
4193 		if( libfsapfs_internal_file_entry_get_data_stream(
4194 		     internal_file_entry,
4195 		     error ) != 1 )
4196 		{
4197 			libcerror_error_set(
4198 			 error,
4199 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4200 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4201 			 "%s: unable to determine data stream.",
4202 			 function );
4203 
4204 			read_count = -1;
4205 		}
4206 	}
4207 	if( read_count != -1 )
4208 	{
4209 		read_count = libfdata_stream_read_buffer(
4210 		              internal_file_entry->data_stream,
4211 		              (intptr_t *) internal_file_entry->file_io_handle,
4212 		              (uint8_t *) buffer,
4213 		              buffer_size,
4214 		              0,
4215 		              error );
4216 
4217 		if( read_count < 0 )
4218 		{
4219 			libcerror_error_set(
4220 			 error,
4221 			 LIBCERROR_ERROR_DOMAIN_IO,
4222 			 LIBCERROR_IO_ERROR_READ_FAILED,
4223 			 "%s: unable to read buffer from data stream.",
4224 			 function );
4225 
4226 			read_count = -1;
4227 		}
4228 	}
4229 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4230 	if( libcthreads_read_write_lock_release_for_write(
4231 	     internal_file_entry->read_write_lock,
4232 	     error ) != 1 )
4233 	{
4234 		libcerror_error_set(
4235 		 error,
4236 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4237 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4238 		 "%s: unable to release read/write lock for writing.",
4239 		 function );
4240 
4241 		return( -1 );
4242 	}
4243 #endif
4244 	return( read_count );
4245 }
4246 
4247 /* Reads data at a specific offset
4248  * Returns the number of bytes read or -1 on error
4249  */
libfsapfs_file_entry_read_buffer_at_offset(libfsapfs_file_entry_t * file_entry,void * buffer,size_t buffer_size,off64_t offset,libcerror_error_t ** error)4250 ssize_t libfsapfs_file_entry_read_buffer_at_offset(
4251          libfsapfs_file_entry_t *file_entry,
4252          void *buffer,
4253          size_t buffer_size,
4254          off64_t offset,
4255          libcerror_error_t **error )
4256 {
4257 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4258 	static char *function                                = "libfsapfs_file_entry_read_buffer_at_offset";
4259 	ssize_t read_count                                   = 0;
4260 
4261 	if( file_entry == NULL )
4262 	{
4263 		libcerror_error_set(
4264 		 error,
4265 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4266 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4267 		 "%s: invalid file entry.",
4268 		 function );
4269 
4270 		return( -1 );
4271 	}
4272 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4273 
4274 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4275 	if( libcthreads_read_write_lock_grab_for_write(
4276 	     internal_file_entry->read_write_lock,
4277 	     error ) != 1 )
4278 	{
4279 		libcerror_error_set(
4280 		 error,
4281 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4282 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4283 		 "%s: unable to grab read/write lock for writing.",
4284 		 function );
4285 
4286 		return( -1 );
4287 	}
4288 #endif
4289 	if( internal_file_entry->data_stream == NULL )
4290 	{
4291 		if( libfsapfs_internal_file_entry_get_data_stream(
4292 		     internal_file_entry,
4293 		     error ) != 1 )
4294 		{
4295 			libcerror_error_set(
4296 			 error,
4297 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4298 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4299 			 "%s: unable to determine data stream.",
4300 			 function );
4301 
4302 			read_count = -1;
4303 		}
4304 	}
4305 	if( read_count != -1 )
4306 	{
4307 		read_count = libfdata_stream_read_buffer_at_offset(
4308 		              internal_file_entry->data_stream,
4309 		              (intptr_t *) internal_file_entry->file_io_handle,
4310 		              (uint8_t *) buffer,
4311 		              buffer_size,
4312 		              offset,
4313 		              0,
4314 		              error );
4315 
4316 		if( read_count < 0 )
4317 		{
4318 			libcerror_error_set(
4319 			 error,
4320 			 LIBCERROR_ERROR_DOMAIN_IO,
4321 			 LIBCERROR_IO_ERROR_READ_FAILED,
4322 			 "%s: unable to read buffer at offset from data stream.",
4323 			 function );
4324 
4325 			read_count = -1;
4326 		}
4327 	}
4328 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4329 	if( libcthreads_read_write_lock_release_for_write(
4330 	     internal_file_entry->read_write_lock,
4331 	     error ) != 1 )
4332 	{
4333 		libcerror_error_set(
4334 		 error,
4335 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4336 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4337 		 "%s: unable to release read/write lock for writing.",
4338 		 function );
4339 
4340 		return( -1 );
4341 	}
4342 #endif
4343 	return( read_count );
4344 }
4345 
4346 /* Seeks a certain offset
4347  * Returns the offset if seek is successful or -1 on error
4348  */
libfsapfs_file_entry_seek_offset(libfsapfs_file_entry_t * file_entry,off64_t offset,int whence,libcerror_error_t ** error)4349 off64_t libfsapfs_file_entry_seek_offset(
4350          libfsapfs_file_entry_t *file_entry,
4351          off64_t offset,
4352          int whence,
4353          libcerror_error_t **error )
4354 {
4355 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4356 	static char *function                                = "libfsapfs_file_entry_seek_offset";
4357 	off64_t result_offset                                = 0;
4358 
4359 	if( file_entry == NULL )
4360 	{
4361 		libcerror_error_set(
4362 		 error,
4363 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4364 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4365 		 "%s: invalid file entry.",
4366 		 function );
4367 
4368 		return( -1 );
4369 	}
4370 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4371 
4372 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4373 	if( libcthreads_read_write_lock_grab_for_write(
4374 	     internal_file_entry->read_write_lock,
4375 	     error ) != 1 )
4376 	{
4377 		libcerror_error_set(
4378 		 error,
4379 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4380 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4381 		 "%s: unable to grab read/write lock for writing.",
4382 		 function );
4383 
4384 		return( -1 );
4385 	}
4386 #endif
4387 	if( internal_file_entry->data_stream == NULL )
4388 	{
4389 		if( libfsapfs_internal_file_entry_get_data_stream(
4390 		     internal_file_entry,
4391 		     error ) != 1 )
4392 		{
4393 			libcerror_error_set(
4394 			 error,
4395 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4396 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4397 			 "%s: unable to determine data stream.",
4398 			 function );
4399 
4400 			result_offset = -1;
4401 		}
4402 	}
4403 	if( result_offset != -1 )
4404 	{
4405 		result_offset = libfdata_stream_seek_offset(
4406 		                 internal_file_entry->data_stream,
4407 		                 offset,
4408 		                 whence,
4409 		                 error );
4410 
4411 		if( result_offset < 0 )
4412 		{
4413 			libcerror_error_set(
4414 			 error,
4415 			 LIBCERROR_ERROR_DOMAIN_IO,
4416 			 LIBCERROR_IO_ERROR_SEEK_FAILED,
4417 			 "%s: unable to seek offset in data stream.",
4418 			 function );
4419 
4420 			result_offset = -1;
4421 		}
4422 	}
4423 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4424 	if( libcthreads_read_write_lock_release_for_write(
4425 	     internal_file_entry->read_write_lock,
4426 	     error ) != 1 )
4427 	{
4428 		libcerror_error_set(
4429 		 error,
4430 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4431 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4432 		 "%s: unable to release read/write lock for writing.",
4433 		 function );
4434 
4435 		return( -1 );
4436 	}
4437 #endif
4438 	return( result_offset );
4439 }
4440 
4441 /* Retrieves the current offset
4442  * Returns the offset if successful or -1 on error
4443  */
libfsapfs_file_entry_get_offset(libfsapfs_file_entry_t * file_entry,off64_t * offset,libcerror_error_t ** error)4444 int libfsapfs_file_entry_get_offset(
4445      libfsapfs_file_entry_t *file_entry,
4446      off64_t *offset,
4447      libcerror_error_t **error )
4448 {
4449 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4450 	static char *function                                = "libfsapfs_file_entry_get_offset";
4451 
4452 	if( file_entry == NULL )
4453 	{
4454 		libcerror_error_set(
4455 		 error,
4456 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4457 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4458 		 "%s: invalid file entry.",
4459 		 function );
4460 
4461 		return( -1 );
4462 	}
4463 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4464 
4465 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4466 	if( libcthreads_read_write_lock_grab_for_write(
4467 	     internal_file_entry->read_write_lock,
4468 	     error ) != 1 )
4469 	{
4470 		libcerror_error_set(
4471 		 error,
4472 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4473 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4474 		 "%s: unable to grab read/write lock for writing.",
4475 		 function );
4476 
4477 		return( -1 );
4478 	}
4479 #endif
4480 	if( internal_file_entry->data_stream == NULL )
4481 	{
4482 		if( libfsapfs_internal_file_entry_get_data_stream(
4483 		     internal_file_entry,
4484 		     error ) != 1 )
4485 		{
4486 			libcerror_error_set(
4487 			 error,
4488 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4489 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4490 			 "%s: unable to determine data stream.",
4491 			 function );
4492 
4493 			goto on_error;
4494 		}
4495 	}
4496 	if( libfdata_stream_get_offset(
4497 	     internal_file_entry->data_stream,
4498 	     offset,
4499 	     error ) != 1 )
4500 	{
4501 		libcerror_error_set(
4502 		 error,
4503 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4504 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4505 		 "%s: unable to retrieve offset from data stream.",
4506 		 function );
4507 
4508 		goto on_error;
4509 	}
4510 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4511 	if( libcthreads_read_write_lock_release_for_write(
4512 	     internal_file_entry->read_write_lock,
4513 	     error ) != 1 )
4514 	{
4515 		libcerror_error_set(
4516 		 error,
4517 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4518 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4519 		 "%s: unable to release read/write lock for writing.",
4520 		 function );
4521 
4522 		return( -1 );
4523 	}
4524 #endif
4525 	return( 1 );
4526 
4527 on_error:
4528 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4529 	libcthreads_read_write_lock_release_for_write(
4530 	 internal_file_entry->read_write_lock,
4531 	 NULL );
4532 #endif
4533 	return( -1 );
4534 }
4535 
4536 /* Determines the data size
4537  * Returns 1 if successful or -1 on error
4538  */
libfsapfs_internal_file_entry_get_data_size(libfsapfs_internal_file_entry_t * internal_file_entry,libcerror_error_t ** error)4539 int libfsapfs_internal_file_entry_get_data_size(
4540      libfsapfs_internal_file_entry_t *internal_file_entry,
4541      libcerror_error_t **error )
4542 {
4543 	uint8_t extended_attribute_data[ 16 ];
4544 
4545 	static char *function = "libfsapfs_internal_file_entry_get_data_size";
4546 	size64_t data_size    = 0;
4547 	ssize_t read_count    = 0;
4548 	int result            = 0;
4549 
4550 	if( internal_file_entry == NULL )
4551 	{
4552 		libcerror_error_set(
4553 		 error,
4554 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4555 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4556 		 "%s: invalid file entry.",
4557 		 function );
4558 
4559 		return( -1 );
4560 	}
4561 	if( internal_file_entry->compressed_data_header != NULL )
4562 	{
4563 		libcerror_error_set(
4564 		 error,
4565 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4566 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4567 		 "%s: invalid file entry - compressed data header value already set.",
4568 		 function );
4569 
4570 		return( -1 );
4571 	}
4572 	if( internal_file_entry->data_size != (size64_t) -1 )
4573 	{
4574 		libcerror_error_set(
4575 		 error,
4576 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4577 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
4578 		 "%s: invalid file entry - data size value already set.",
4579 		 function );
4580 
4581 		return( -1 );
4582 	}
4583 	if( internal_file_entry->extended_attributes == NULL )
4584 	{
4585 		if( libfsapfs_internal_file_entry_get_extended_attributes(
4586 		     internal_file_entry,
4587 		     error ) != 1 )
4588 		{
4589 			libcerror_error_set(
4590 			 error,
4591 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4592 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4593 			 "%s: unable to determine extended attributes.",
4594 			 function );
4595 
4596 			return( -1 );
4597 		}
4598 	}
4599 	if( internal_file_entry->compressed_data_extended_attribute != NULL )
4600 	{
4601 		read_count = libfsapfs_extended_attribute_read_buffer_at_offset(
4602 		              internal_file_entry->compressed_data_extended_attribute,
4603 		              extended_attribute_data,
4604 		              16,
4605 		              0,
4606 		              error );
4607 
4608 		if( read_count != (ssize_t) 16 )
4609 		{
4610 			libcerror_error_set(
4611 			 error,
4612 			 LIBCERROR_ERROR_DOMAIN_IO,
4613 			 LIBCERROR_IO_ERROR_READ_FAILED,
4614 			 "%s: unable to read extended attribute data.",
4615 			 function );
4616 
4617 			return( -1 );
4618 		}
4619 		if( libfsapfs_compressed_data_header_initialize(
4620 		     &( internal_file_entry->compressed_data_header ),
4621 		     error ) != 1 )
4622 		{
4623 			libcerror_error_set(
4624 			 error,
4625 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4626 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
4627 			 "%s: unable to create compressed data header.",
4628 			 function );
4629 
4630 			goto on_error;
4631 		}
4632 		result = libfsapfs_compressed_data_header_read_data(
4633 		          internal_file_entry->compressed_data_header,
4634 		          extended_attribute_data,
4635 		          16,
4636 		          error );
4637 
4638 		if( result == -1 )
4639 		{
4640 			libcerror_error_set(
4641 			 error,
4642 			 LIBCERROR_ERROR_DOMAIN_IO,
4643 			 LIBCERROR_IO_ERROR_READ_FAILED,
4644 			 "%s: unable to read compressed data header.",
4645 			 function );
4646 
4647 			goto on_error;
4648 		}
4649 		else if( result != 0 )
4650 		{
4651 			data_size = internal_file_entry->compressed_data_header->uncompressed_data_size;
4652 		}
4653 		else
4654 		{
4655 			if( libfsapfs_compressed_data_header_free(
4656 			     &( internal_file_entry->compressed_data_header ),
4657 			     error ) != 1 )
4658 			{
4659 				libcerror_error_set(
4660 				 error,
4661 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4662 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
4663 				 "%s: unable to free compressed data header.",
4664 				 function );
4665 
4666 				goto on_error;
4667 			}
4668 		}
4669 	}
4670 	if( result == 0 )
4671 	{
4672 		if( libfsapfs_inode_get_data_stream_size(
4673 		     internal_file_entry->inode,
4674 		     &data_size,
4675 		     error ) != 1 )
4676 		{
4677 			libcerror_error_set(
4678 			 error,
4679 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4680 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4681 			 "%s: unable to retrieve data stream size from inode.",
4682 			 function );
4683 
4684 			return( -1 );
4685 		}
4686 	}
4687 	internal_file_entry->data_size = data_size;
4688 
4689 	return( 1 );
4690 
4691 on_error:
4692 	if( internal_file_entry->compressed_data_header != NULL )
4693 	{
4694 		libfsapfs_compressed_data_header_free(
4695 		 &( internal_file_entry->compressed_data_header ),
4696 		 NULL );
4697 	}
4698 	return( -1 );
4699 }
4700 
4701 /* Retrieves the size of the data stream object
4702  * Returns 1 if successful or -1 on error
4703  */
libfsapfs_file_entry_get_size(libfsapfs_file_entry_t * file_entry,size64_t * size,libcerror_error_t ** error)4704 int libfsapfs_file_entry_get_size(
4705      libfsapfs_file_entry_t *file_entry,
4706      size64_t *size,
4707      libcerror_error_t **error )
4708 {
4709 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4710 	static char *function                                = "libfsapfs_file_entry_get_size";
4711 
4712 	if( file_entry == NULL )
4713 	{
4714 		libcerror_error_set(
4715 		 error,
4716 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4717 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4718 		 "%s: invalid file entry.",
4719 		 function );
4720 
4721 		return( -1 );
4722 	}
4723 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4724 
4725 	if( size == NULL )
4726 	{
4727 		libcerror_error_set(
4728 		 error,
4729 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4730 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4731 		 "%s: invalid size.",
4732 		 function );
4733 
4734 		return( -1 );
4735 	}
4736 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4737 	if( libcthreads_read_write_lock_grab_for_write(
4738 	     internal_file_entry->read_write_lock,
4739 	     error ) != 1 )
4740 	{
4741 		libcerror_error_set(
4742 		 error,
4743 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4744 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4745 		 "%s: unable to grab read/write lock for writing.",
4746 		 function );
4747 
4748 		return( -1 );
4749 	}
4750 #endif
4751 	if( internal_file_entry->data_size == (size64_t) -1 )
4752 	{
4753 		if( libfsapfs_internal_file_entry_get_data_size(
4754 		     internal_file_entry,
4755 		     error ) != 1 )
4756 		{
4757 			libcerror_error_set(
4758 			 error,
4759 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4760 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4761 			 "%s: unable to determine data size.",
4762 			 function );
4763 
4764 			goto on_error;
4765 		}
4766 	}
4767 	*size = internal_file_entry->data_size;
4768 
4769 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4770 	if( libcthreads_read_write_lock_release_for_write(
4771 	     internal_file_entry->read_write_lock,
4772 	     error ) != 1 )
4773 	{
4774 		libcerror_error_set(
4775 		 error,
4776 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4777 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4778 		 "%s: unable to release read/write lock for writing.",
4779 		 function );
4780 
4781 		return( -1 );
4782 	}
4783 #endif
4784 	return( 1 );
4785 
4786 on_error:
4787 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4788 	libcthreads_read_write_lock_release_for_write(
4789 	 internal_file_entry->read_write_lock,
4790 	 NULL );
4791 #endif
4792 	return( -1 );
4793 }
4794 
4795 /* Retrieves the number of extents
4796  * Returns 1 if successful or -1 on error
4797  */
libfsapfs_file_entry_get_number_of_extents(libfsapfs_file_entry_t * file_entry,int * number_of_extents,libcerror_error_t ** error)4798 int libfsapfs_file_entry_get_number_of_extents(
4799      libfsapfs_file_entry_t *file_entry,
4800      int *number_of_extents,
4801      libcerror_error_t **error )
4802 {
4803 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4804 	static char *function                                = "libfsapfs_file_entry_get_number_of_extents";
4805 
4806 	if( file_entry == NULL )
4807 	{
4808 		libcerror_error_set(
4809 		 error,
4810 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4811 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4812 		 "%s: invalid file entry.",
4813 		 function );
4814 
4815 		return( -1 );
4816 	}
4817 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4818 
4819 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4820 	if( libcthreads_read_write_lock_grab_for_write(
4821 	     internal_file_entry->read_write_lock,
4822 	     error ) != 1 )
4823 	{
4824 		libcerror_error_set(
4825 		 error,
4826 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4827 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4828 		 "%s: unable to grab read/write lock for writing.",
4829 		 function );
4830 
4831 		return( -1 );
4832 	}
4833 #endif
4834 	if( internal_file_entry->file_extents == NULL )
4835 	{
4836 		if( libfsapfs_internal_file_entry_get_file_extents(
4837 		     internal_file_entry,
4838 		     error ) != 1 )
4839 		{
4840 			libcerror_error_set(
4841 			 error,
4842 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4843 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4844 			 "%s: unable to determine file extents.",
4845 			 function );
4846 
4847 			goto on_error;
4848 		}
4849 	}
4850 	if( libcdata_array_get_number_of_entries(
4851 	     internal_file_entry->file_extents,
4852 	     number_of_extents,
4853 	     error ) != 1 )
4854 	{
4855 		libcerror_error_set(
4856 		 error,
4857 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4858 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4859 		 "%s: unable to retrieve number of entries from array.",
4860 		 function );
4861 
4862 		goto on_error;
4863 	}
4864 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4865 	if( libcthreads_read_write_lock_release_for_write(
4866 	     internal_file_entry->read_write_lock,
4867 	     error ) != 1 )
4868 	{
4869 		libcerror_error_set(
4870 		 error,
4871 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4872 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4873 		 "%s: unable to release read/write lock for writing.",
4874 		 function );
4875 
4876 		return( -1 );
4877 	}
4878 #endif
4879 	return( 1 );
4880 
4881 on_error:
4882 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4883 	libcthreads_read_write_lock_release_for_write(
4884 	 internal_file_entry->read_write_lock,
4885 	 NULL );
4886 #endif
4887 	return( -1 );
4888 }
4889 
4890 /* Retrieves a specific extent
4891  * Returns 1 if successful or -1 on error
4892  */
libfsapfs_file_entry_get_extent_by_index(libfsapfs_file_entry_t * file_entry,int extent_index,off64_t * extent_offset,size64_t * extent_size,uint32_t * extent_flags,libcerror_error_t ** error)4893 int libfsapfs_file_entry_get_extent_by_index(
4894      libfsapfs_file_entry_t *file_entry,
4895      int extent_index,
4896      off64_t *extent_offset,
4897      size64_t *extent_size,
4898      uint32_t *extent_flags,
4899      libcerror_error_t **error )
4900 {
4901 	libfsapfs_file_extent_t *file_extent                 = NULL;
4902 	libfsapfs_internal_file_entry_t *internal_file_entry = NULL;
4903 	static char *function                                = "libfsapfs_file_entry_get_extent_by_index";
4904 
4905 	if( file_entry == NULL )
4906 	{
4907 		libcerror_error_set(
4908 		 error,
4909 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4910 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4911 		 "%s: invalid file entry.",
4912 		 function );
4913 
4914 		return( -1 );
4915 	}
4916 	internal_file_entry = (libfsapfs_internal_file_entry_t *) file_entry;
4917 
4918 	if( internal_file_entry->io_handle == NULL )
4919 	{
4920 		libcerror_error_set(
4921 		 error,
4922 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4923 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
4924 		 "%s: invalid internal file entry - missing IO handle.",
4925 		 function );
4926 
4927 		return( -1 );
4928 	}
4929 	if( extent_offset == NULL )
4930 	{
4931 		libcerror_error_set(
4932 		 error,
4933 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4934 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4935 		 "%s: invalid extent offset.",
4936 		 function );
4937 
4938 		return( -1 );
4939 	}
4940 	if( extent_size == NULL )
4941 	{
4942 		libcerror_error_set(
4943 		 error,
4944 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4945 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4946 		 "%s: invalid extent size.",
4947 		 function );
4948 
4949 		return( -1 );
4950 	}
4951 	if( extent_flags == NULL )
4952 	{
4953 		libcerror_error_set(
4954 		 error,
4955 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
4956 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
4957 		 "%s: invalid extent flags.",
4958 		 function );
4959 
4960 		return( -1 );
4961 	}
4962 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
4963 	if( libcthreads_read_write_lock_grab_for_write(
4964 	     internal_file_entry->read_write_lock,
4965 	     error ) != 1 )
4966 	{
4967 		libcerror_error_set(
4968 		 error,
4969 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4970 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
4971 		 "%s: unable to grab read/write lock for writing.",
4972 		 function );
4973 
4974 		return( -1 );
4975 	}
4976 #endif
4977 	if( internal_file_entry->file_extents == NULL )
4978 	{
4979 		if( libfsapfs_internal_file_entry_get_file_extents(
4980 		     internal_file_entry,
4981 		     error ) != 1 )
4982 		{
4983 			libcerror_error_set(
4984 			 error,
4985 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
4986 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
4987 			 "%s: unable to determine file extents.",
4988 			 function );
4989 
4990 			goto on_error;
4991 		}
4992 	}
4993 	if( libcdata_array_get_entry_by_index(
4994 	     internal_file_entry->file_extents,
4995 	     extent_index,
4996 	     (intptr_t **) &file_extent,
4997 	     error ) != 1 )
4998 	{
4999 		libcerror_error_set(
5000 		 error,
5001 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
5002 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
5003 		 "%s: unable to retrieve file extent: %d.",
5004 		 function,
5005 		 extent_index );
5006 
5007 		goto on_error;
5008 	}
5009 	if( file_extent == NULL )
5010 	{
5011 		libcerror_error_set(
5012 		 error,
5013 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
5014 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
5015 		 "%s: missing file extent: %d.",
5016 		 function,
5017 		 extent_index );
5018 
5019 		goto on_error;
5020 	}
5021 	*extent_offset = file_extent->physical_block_number * internal_file_entry->io_handle->block_size;
5022 	*extent_size   = file_extent->data_size;
5023 	*extent_flags  = 0;
5024 
5025 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5026 	if( libcthreads_read_write_lock_release_for_write(
5027 	     internal_file_entry->read_write_lock,
5028 	     error ) != 1 )
5029 	{
5030 		libcerror_error_set(
5031 		 error,
5032 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
5033 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
5034 		 "%s: unable to release read/write lock for writing.",
5035 		 function );
5036 
5037 		return( -1 );
5038 	}
5039 #endif
5040 	return( 1 );
5041 
5042 on_error:
5043 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
5044 	libcthreads_read_write_lock_release_for_write(
5045 	 internal_file_entry->read_write_lock,
5046 	 NULL );
5047 #endif
5048 	return( -1 );
5049 }
5050 
5051