1 /*
2  * Extended attribute 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 <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libfsapfs_data_stream.h"
28 #include "libfsapfs_debug.h"
29 #include "libfsapfs_encryption_context.h"
30 #include "libfsapfs_extended_attribute.h"
31 #include "libfsapfs_file_extent.h"
32 #include "libfsapfs_file_system_btree.h"
33 #include "libfsapfs_io_handle.h"
34 #include "libfsapfs_libbfio.h"
35 #include "libfsapfs_libcerror.h"
36 #include "libfsapfs_libcnotify.h"
37 #include "libfsapfs_libcthreads.h"
38 #include "libfsapfs_libfdata.h"
39 #include "libfsapfs_libfdatetime.h"
40 #include "libfsapfs_libuna.h"
41 #include "libfsapfs_types.h"
42 
43 #include "fsapfs_file_system.h"
44 
45 /* Creates an extended_attribute
46  * Make sure the value extended_attribute is referencing, is set to NULL
47  * Returns 1 if successful or -1 on error
48  */
libfsapfs_extended_attribute_initialize(libfsapfs_extended_attribute_t ** extended_attribute,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,libcerror_error_t ** error)49 int libfsapfs_extended_attribute_initialize(
50      libfsapfs_extended_attribute_t **extended_attribute,
51      libfsapfs_io_handle_t *io_handle,
52      libbfio_handle_t *file_io_handle,
53      libfsapfs_encryption_context_t *encryption_context,
54      libfsapfs_file_system_btree_t *file_system_btree,
55      libcerror_error_t **error )
56 {
57 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
58 	static char *function                                                = "libfsapfs_extended_attribute_initialize";
59 
60 	if( extended_attribute == NULL )
61 	{
62 		libcerror_error_set(
63 		 error,
64 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
65 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
66 		 "%s: invalid extended attribute.",
67 		 function );
68 
69 		return( -1 );
70 	}
71 	if( *extended_attribute != NULL )
72 	{
73 		libcerror_error_set(
74 		 error,
75 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
76 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
77 		 "%s: invalid extended attribute value already set.",
78 		 function );
79 
80 		return( -1 );
81 	}
82 	internal_extended_attribute = memory_allocate_structure(
83 	                               libfsapfs_internal_extended_attribute_t );
84 
85 	if( internal_extended_attribute == NULL )
86 	{
87 		libcerror_error_set(
88 		 error,
89 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
90 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
91 		 "%s: unable to create extended attribute.",
92 		 function );
93 
94 		goto on_error;
95 	}
96 	if( memory_set(
97 	     internal_extended_attribute,
98 	     0,
99 	     sizeof( libfsapfs_internal_extended_attribute_t ) ) == NULL )
100 	{
101 		libcerror_error_set(
102 		 error,
103 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
104 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
105 		 "%s: unable to clear extended attribute.",
106 		 function );
107 
108 		memory_free(
109 		 internal_extended_attribute );
110 
111 		return( -1 );
112 	}
113 	internal_extended_attribute->io_handle          = io_handle;
114 	internal_extended_attribute->file_io_handle     = file_io_handle;
115 	internal_extended_attribute->encryption_context = encryption_context;
116 	internal_extended_attribute->file_system_btree  = file_system_btree;
117 
118 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
119 	if( libcthreads_read_write_lock_initialize(
120 	     &( internal_extended_attribute->read_write_lock ),
121 	     error ) != 1 )
122 	{
123 		libcerror_error_set(
124 		 error,
125 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
126 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
127 		 "%s: unable to initialize read/write lock.",
128 		 function );
129 
130 		goto on_error;
131 	}
132 #endif
133 	*extended_attribute = (libfsapfs_extended_attribute_t *) internal_extended_attribute;
134 
135 	return( 1 );
136 
137 on_error:
138 	if( internal_extended_attribute != NULL )
139 	{
140 		memory_free(
141 		 internal_extended_attribute );
142 	}
143 	return( -1 );
144 }
145 
146 /* Frees an extended attribute
147  * Returns 1 if successful or -1 on error
148  */
libfsapfs_extended_attribute_free(libfsapfs_extended_attribute_t ** extended_attribute,libcerror_error_t ** error)149 int libfsapfs_extended_attribute_free(
150      libfsapfs_extended_attribute_t **extended_attribute,
151      libcerror_error_t **error )
152 {
153 	static char *function = "libfsapfs_extended_attribute_free";
154 
155 	if( extended_attribute == NULL )
156 	{
157 		libcerror_error_set(
158 		 error,
159 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161 		 "%s: invalid extended attribute.",
162 		 function );
163 
164 		return( -1 );
165 	}
166 	if( *extended_attribute != NULL )
167 	{
168 		*extended_attribute = NULL;
169 	}
170 	return( 1 );
171 }
172 
173 /* Frees an extended attribute
174  * Returns 1 if successful or -1 on error
175  */
libfsapfs_internal_extended_attribute_free(libfsapfs_internal_extended_attribute_t ** internal_extended_attribute,libcerror_error_t ** error)176 int libfsapfs_internal_extended_attribute_free(
177      libfsapfs_internal_extended_attribute_t **internal_extended_attribute,
178      libcerror_error_t **error )
179 {
180 	static char *function = "libfsapfs_extended_attribute_free";
181 	int result            = 1;
182 
183 	if( internal_extended_attribute == NULL )
184 	{
185 		libcerror_error_set(
186 		 error,
187 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
189 		 "%s: invalid extended attribute.",
190 		 function );
191 
192 		return( -1 );
193 	}
194 	if( *internal_extended_attribute != NULL )
195 	{
196 #if defined( HAVE_MULTI_THREAD_SUPPORT ) && !defined( HAVE_LOCAL_LIBFSAPFS )
197 		if( libcthreads_read_write_lock_free(
198 		     &( ( *internal_extended_attribute )->read_write_lock ),
199 		     error ) != 1 )
200 		{
201 			libcerror_error_set(
202 			 error,
203 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
204 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
205 			 "%s: unable to free read/write lock.",
206 			 function );
207 
208 			result = -1;
209 		}
210 #endif
211 		if( ( *internal_extended_attribute )->data_stream != NULL )
212 		{
213 			if( libfdata_stream_free(
214 			     &( ( *internal_extended_attribute )->data_stream ),
215 			     error ) != 1 )
216 			{
217 				libcerror_error_set(
218 				 error,
219 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
220 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
221 				 "%s: unable to free data stream.",
222 				 function );
223 
224 				result = -1;
225 			}
226 		}
227 		if( ( *internal_extended_attribute )->file_extents != NULL )
228 		{
229 			if( libcdata_array_free(
230 			     &( ( *internal_extended_attribute )->file_extents ),
231 			     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
232 			     error ) != 1 )
233 			{
234 				libcerror_error_set(
235 				 error,
236 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
237 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
238 				 "%s: unable to free file extents array.",
239 				 function );
240 
241 				result = -1;
242 			}
243 		}
244 		if( ( *internal_extended_attribute )->data != NULL )
245 		{
246 			memory_free(
247 			 ( *internal_extended_attribute )->data );
248 		}
249 		if( ( *internal_extended_attribute )->name != NULL )
250 		{
251 			memory_free(
252 			 ( *internal_extended_attribute )->name );
253 		}
254 		memory_free(
255 		 *internal_extended_attribute );
256 
257 		*internal_extended_attribute = NULL;
258 	}
259 	return( result );
260 }
261 
262 /* Reads the extended attribute key data
263  * Returns 1 if successful or -1 on error
264  */
libfsapfs_extended_attribute_read_key_data(libfsapfs_extended_attribute_t * extended_attribute,const uint8_t * data,size_t data_size,libcerror_error_t ** error)265 int libfsapfs_extended_attribute_read_key_data(
266      libfsapfs_extended_attribute_t *extended_attribute,
267      const uint8_t *data,
268      size_t data_size,
269      libcerror_error_t **error )
270 {
271 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
272 	static char *function                                                = "libfsapfs_extended_attribute_read_key_data";
273 	size_t data_offset                                                   = 0;
274 	uint16_t name_size                                                   = 0;
275 
276 #if defined( HAVE_DEBUG_OUTPUT )
277 	uint64_t value_64bit                                                 = 0;
278 #endif
279 
280 	if( extended_attribute == NULL )
281 	{
282 		libcerror_error_set(
283 		 error,
284 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
285 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
286 		 "%s: invalid extended attribute.",
287 		 function );
288 
289 		return( -1 );
290 	}
291 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
292 
293 	if( internal_extended_attribute->name != NULL )
294 	{
295 		libcerror_error_set(
296 		 error,
297 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
298 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
299 		 "%s: invalid extended attribute - name value already set.",
300 		 function );
301 
302 		return( -1 );
303 	}
304 	if( data == NULL )
305 	{
306 		libcerror_error_set(
307 		 error,
308 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
309 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
310 		 "%s: invalid data.",
311 		 function );
312 
313 		return( -1 );
314 	}
315 	if( ( data_size < sizeof( fsapfs_file_system_btree_key_extended_attribute_t ) )
316 	 || ( data_size > (size_t) SSIZE_MAX ) )
317 	{
318 		libcerror_error_set(
319 		 error,
320 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
321 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
322 		 "%s: invalid data size value out of bounds.",
323 		 function );
324 
325 		return( -1 );
326 	}
327 #if defined( HAVE_DEBUG_OUTPUT )
328 	if( libcnotify_verbose != 0 )
329 	{
330 		libcnotify_printf(
331 		 "%s: extended attribute key data:\n",
332 		 function );
333 		libcnotify_print_data(
334 		 data,
335 		 data_size,
336 		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
337 	}
338 #endif
339 	byte_stream_copy_to_uint16_little_endian(
340 	 ( (fsapfs_file_system_btree_key_extended_attribute_t *) data )->name_size,
341 	 name_size );
342 
343 #if defined( HAVE_DEBUG_OUTPUT )
344 	if( libcnotify_verbose != 0 )
345 	{
346 		byte_stream_copy_to_uint64_little_endian(
347 		 ( (fsapfs_file_system_btree_key_extended_attribute_t *) data )->file_system_identifier,
348 		 value_64bit );
349 		libcnotify_printf(
350 		 "%s: parent identifier\t\t: 0x%08" PRIx64 "\n",
351 		 function,
352 		 value_64bit );
353 
354 		libcnotify_printf(
355 		 "%s: name size\t\t\t: %" PRIu16 "\n",
356 		 function,
357 		 name_size );
358 	}
359 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
360 
361 	data_offset = sizeof( fsapfs_file_system_btree_key_extended_attribute_t );
362 
363 	if( ( name_size == 0 )
364 	 || ( (size_t) name_size > ( data_size - data_offset ) ) )
365 	{
366 		libcerror_error_set(
367 		 error,
368 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
369 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
370 		 "%s: invalid name size value out of bounds.",
371 		 function );
372 
373 		goto on_error;
374 	}
375 #if defined( HAVE_DEBUG_OUTPUT )
376 	if( libcnotify_verbose != 0 )
377 	{
378 		libcnotify_printf(
379 		 "%s: name data:\n",
380 		 function );
381 		libcnotify_print_data(
382 		 &( data[ data_offset ] ),
383 		 (size_t) name_size,
384 		 0 );
385 	}
386 #endif
387 	internal_extended_attribute->name = (uint8_t *) memory_allocate(
388 	                                                 sizeof( uint8_t ) * name_size );
389 
390 	if( internal_extended_attribute->name == NULL )
391 	{
392 		libcerror_error_set(
393 		 error,
394 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
395 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
396 		 "%s: unable to create name.",
397 		 function );
398 
399 		goto on_error;
400 	}
401 	internal_extended_attribute->name_size = name_size;
402 
403 	if( memory_copy(
404 	     internal_extended_attribute->name,
405 	     &( data[ data_offset ] ),
406 	     name_size ) == NULL )
407 	{
408 		libcerror_error_set(
409 		 error,
410 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
411 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
412 		 "%s: unable to copy name.",
413 		 function );
414 
415 		goto on_error;
416 	}
417 	return( 1 );
418 
419 on_error:
420 	if( internal_extended_attribute->name != NULL )
421 	{
422 		memory_free(
423 		 internal_extended_attribute->name );
424 
425 		internal_extended_attribute->name = NULL;
426 	}
427 	internal_extended_attribute->name_size = 0;
428 
429 	return( -1 );
430 }
431 
432 /* Reads the extended attribute value data
433  * Returns 1 if successful or -1 on error
434  */
libfsapfs_extended_attribute_read_value_data(libfsapfs_extended_attribute_t * extended_attribute,const uint8_t * data,size_t data_size,libcerror_error_t ** error)435 int libfsapfs_extended_attribute_read_value_data(
436      libfsapfs_extended_attribute_t *extended_attribute,
437      const uint8_t *data,
438      size_t data_size,
439      libcerror_error_t **error )
440 {
441 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
442 	static char *function                                                = "libfsapfs_extended_attribute_read_value_data";
443 	const uint8_t *extended_attribute_data                               = NULL;
444 	size_t data_offset                                                   = 0;
445 	uint16_t extended_attribute_flags                                    = 0;
446 	uint16_t extended_attribute_data_size                                = 0;
447 
448 #if defined( HAVE_DEBUG_OUTPUT )
449 	uint64_t value_64bit                                                 = 0;
450 #endif
451 
452 	if( extended_attribute == NULL )
453 	{
454 		libcerror_error_set(
455 		 error,
456 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
458 		 "%s: invalid extended attribute.",
459 		 function );
460 
461 		return( -1 );
462 	}
463 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
464 
465 	if( internal_extended_attribute->data != NULL )
466 	{
467 		libcerror_error_set(
468 		 error,
469 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
470 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
471 		 "%s: invalid extended attribute - data value already set.",
472 		 function );
473 
474 		return( -1 );
475 	}
476 	if( data == NULL )
477 	{
478 		libcerror_error_set(
479 		 error,
480 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
481 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
482 		 "%s: invalid data.",
483 		 function );
484 
485 		return( -1 );
486 	}
487 	if( ( data_size < sizeof( fsapfs_file_system_btree_value_extended_attribute_t ) )
488 	 || ( data_size > (size_t) SSIZE_MAX ) )
489 	{
490 		libcerror_error_set(
491 		 error,
492 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
493 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
494 		 "%s: invalid data size value out of bounds.",
495 		 function );
496 
497 		return( -1 );
498 	}
499 #if defined( HAVE_DEBUG_OUTPUT )
500 	if( libcnotify_verbose != 0 )
501 	{
502 		libcnotify_printf(
503 		 "%s: extended attribute value data:\n",
504 		 function );
505 		libcnotify_print_data(
506 		 data,
507 		 data_size,
508 		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
509 	}
510 #endif
511 	byte_stream_copy_to_uint16_little_endian(
512 	 ( (fsapfs_file_system_btree_value_extended_attribute_t *) data )->flags,
513 	 extended_attribute_flags );
514 
515 	byte_stream_copy_to_uint16_little_endian(
516 	 ( (fsapfs_file_system_btree_value_extended_attribute_t *) data )->data_size,
517 	 extended_attribute_data_size );
518 
519 #if defined( HAVE_DEBUG_OUTPUT )
520 	if( libcnotify_verbose != 0 )
521 	{
522 		libcnotify_printf(
523 		 "%s: flags\t\t\t: 0x%04" PRIx16 "\n",
524 		 function,
525 		 extended_attribute_flags );
526 		libfsapfs_debug_print_extended_attribute_flags(
527 		 extended_attribute_flags );
528 		libcnotify_printf(
529 		 "\n" );
530 
531 		libcnotify_printf(
532 		 "%s: data size\t\t\t: %" PRIu16 "\n",
533 		 function,
534 		 extended_attribute_data_size );
535 
536 		libcnotify_printf(
537 		 "\n" );
538 	}
539 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
540 
541 	data_offset = sizeof( fsapfs_file_system_btree_value_extended_attribute_t );
542 
543 	if( ( extended_attribute_data_size != 0 )
544 	 && ( (size_t) extended_attribute_data_size > ( data_size - data_offset ) ) )
545 	{
546 		libcerror_error_set(
547 		 error,
548 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
549 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
550 		 "%s: invalid extended attribute data size value out of bounds.",
551 		 function );
552 
553 		goto on_error;
554 	}
555 	extended_attribute_data = &( data[ data_offset ] );
556 
557 #if defined( HAVE_DEBUG_OUTPUT )
558 	if( libcnotify_verbose != 0 )
559 	{
560 		libcnotify_printf(
561 		 "%s: extended attribute data:\n",
562 		 function );
563 		libcnotify_print_data(
564 		 extended_attribute_data,
565 		 (size_t) extended_attribute_data_size,
566 		 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
567 	}
568 #endif
569 	if( ( extended_attribute_flags & 0x0001 ) != 0 )
570 	{
571 		if( (size_t) extended_attribute_data_size != sizeof( fsapfs_file_system_extended_attribute_data_stream_t ) )
572 		{
573 			libcerror_error_set(
574 			 error,
575 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
576 			 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
577 			 "%s: unsupported extended attribute data size.",
578 			 function );
579 
580 			goto on_error;
581 		}
582 		byte_stream_copy_to_uint64_little_endian(
583 		 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->data_stream_identifier,
584 		 internal_extended_attribute->data_stream_identifier );
585 
586 		byte_stream_copy_to_uint64_little_endian(
587 		 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->used_size,
588 		 internal_extended_attribute->data_stream_size );
589 
590 #if defined( HAVE_DEBUG_OUTPUT )
591 		if( libcnotify_verbose != 0 )
592 		{
593 			libcnotify_printf(
594 			 "%s: data stream indentifier\t: %" PRIu64 "\n",
595 			 function,
596 			 internal_extended_attribute->data_stream_identifier );
597 
598 			libcnotify_printf(
599 			 "%s: used size\t\t\t: %" PRIu64 "\n",
600 			 function,
601 			 internal_extended_attribute->data_stream_size );
602 
603 			byte_stream_copy_to_uint64_little_endian(
604 			 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->allocated_size,
605 			 value_64bit );
606 			libcnotify_printf(
607 			 "%s: allocated size\t\t: %" PRIu64 "\n",
608 			 function,
609 			 value_64bit );
610 
611 			byte_stream_copy_to_uint64_little_endian(
612 			 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->encryption_identifier,
613 			 value_64bit );
614 			libcnotify_printf(
615 			 "%s: encryption identifier\t: %" PRIu64 "\n",
616 			 function,
617 			 value_64bit );
618 
619 			byte_stream_copy_to_uint64_little_endian(
620 			 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->number_of_bytes_written,
621 			 value_64bit );
622 			libcnotify_printf(
623 			 "%s: number of bytes written\t: %" PRIu64 "\n",
624 			 function,
625 			 value_64bit );
626 
627 			byte_stream_copy_to_uint64_little_endian(
628 			 ( (fsapfs_file_system_extended_attribute_data_stream_t *) extended_attribute_data )->number_of_bytes_read,
629 			 value_64bit );
630 			libcnotify_printf(
631 			 "%s: number of bytes read\t: %" PRIu64 "\n",
632 			 function,
633 			 value_64bit );
634 
635 			libcnotify_printf(
636 			 "\n" );
637 		}
638 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
639 	}
640 	else if( ( ( extended_attribute_flags & 0x0002 ) != 0 )
641 	      && ( extended_attribute_data_size > 0 ) )
642 	{
643 		internal_extended_attribute->data = (uint8_t *) memory_allocate(
644 		                                                 sizeof( uint8_t ) * extended_attribute_data_size );
645 
646 		if( internal_extended_attribute->data == NULL )
647 		{
648 			libcerror_error_set(
649 			 error,
650 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
651 			 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
652 			 "%s: unable to create data.",
653 			 function );
654 
655 			goto on_error;
656 		}
657 		internal_extended_attribute->data_stream_size = (size64_t) extended_attribute_data_size;
658 
659 		if( memory_copy(
660 		     internal_extended_attribute->data,
661 		     extended_attribute_data,
662 		     extended_attribute_data_size ) == NULL )
663 		{
664 			libcerror_error_set(
665 			 error,
666 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
667 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
668 			 "%s: unable to copy data.",
669 			 function );
670 
671 			goto on_error;
672 		}
673 	}
674 	return( 1 );
675 
676 on_error:
677 	if( internal_extended_attribute->data != NULL )
678 	{
679 		memory_free(
680 		 internal_extended_attribute->data );
681 
682 		internal_extended_attribute->data = NULL;
683 	}
684 	internal_extended_attribute->data_stream_size = 0;
685 
686 	return( -1 );
687 }
688 
689 /* Retrieves the data stream
690  * Returns 1 if successful or -1 on error
691  */
libfsapfs_extended_attribute_get_data_stream(libfsapfs_extended_attribute_t * extended_attribute,libfdata_stream_t ** data_stream,libcerror_error_t ** error)692 int libfsapfs_extended_attribute_get_data_stream(
693      libfsapfs_extended_attribute_t *extended_attribute,
694      libfdata_stream_t **data_stream,
695      libcerror_error_t **error )
696 {
697 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
698 	static char *function                                                = "libfsapfs_extended_attribute_get_data_stream";
699 
700 	if( extended_attribute == NULL )
701 	{
702 		libcerror_error_set(
703 		 error,
704 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
705 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
706 		 "%s: invalid extended attribute.",
707 		 function );
708 
709 		return( -1 );
710 	}
711 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
712 
713 	if( data_stream == NULL )
714 	{
715 		libcerror_error_set(
716 		 error,
717 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
718 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
719 		 "%s: invalid data stream.",
720 		 function );
721 
722 		return( -1 );
723 	}
724 	if( internal_extended_attribute->data_stream == NULL )
725 	{
726 		if( libfsapfs_internal_extended_attribute_get_data_stream(
727 		     internal_extended_attribute,
728 		     error ) != 1 )
729 		{
730 			libcerror_error_set(
731 			 error,
732 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
733 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
734 			 "%s: unable to determine data stream.",
735 			 function );
736 
737 			return( -1 );
738 		}
739 	}
740 	*data_stream = internal_extended_attribute->data_stream;
741 
742 	return( 1 );
743 }
744 
745 /* Retrieves the identifier
746  * Returns 1 if successful or -1 on error
747  */
libfsapfs_extended_attribute_get_identifier(libfsapfs_extended_attribute_t * extended_attribute,uint64_t * identifier,libcerror_error_t ** error)748 int libfsapfs_extended_attribute_get_identifier(
749      libfsapfs_extended_attribute_t *extended_attribute,
750      uint64_t *identifier,
751      libcerror_error_t **error )
752 {
753 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
754 	static char *function                                                = "libfsapfs_extended_attribute_get_identifier";
755 
756 	if( extended_attribute == NULL )
757 	{
758 		libcerror_error_set(
759 		 error,
760 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
761 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
762 		 "%s: invalid extended attribute.",
763 		 function );
764 
765 		return( -1 );
766 	}
767 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
768 
769 	if( identifier == NULL )
770 	{
771 		libcerror_error_set(
772 		 error,
773 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
774 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
775 		 "%s: invalid identifier.",
776 		 function );
777 
778 		return( -1 );
779 	}
780 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
781 	if( libcthreads_read_write_lock_grab_for_read(
782 	     internal_extended_attribute->read_write_lock,
783 	     error ) != 1 )
784 	{
785 		libcerror_error_set(
786 		 error,
787 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
788 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
789 		 "%s: unable to grab read/write lock for reading.",
790 		 function );
791 
792 		return( -1 );
793 	}
794 #endif
795 	*identifier = internal_extended_attribute->identifier;
796 
797 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
798 	if( libcthreads_read_write_lock_release_for_read(
799 	     internal_extended_attribute->read_write_lock,
800 	     error ) != 1 )
801 	{
802 		libcerror_error_set(
803 		 error,
804 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
805 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
806 		 "%s: unable to release read/write lock for reading.",
807 		 function );
808 
809 		return( -1 );
810 	}
811 #endif
812 	return( 1 );
813 }
814 
815 /* Retrieves the size of the UTF-8 encoded name
816  * The returned size includes the end of string character
817  * Returns 1 if successful or -1 on error
818  */
libfsapfs_extended_attribute_get_utf8_name_size(libfsapfs_extended_attribute_t * extended_attribute,size_t * utf8_string_size,libcerror_error_t ** error)819 int libfsapfs_extended_attribute_get_utf8_name_size(
820      libfsapfs_extended_attribute_t *extended_attribute,
821      size_t *utf8_string_size,
822      libcerror_error_t **error )
823 {
824 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
825 	static char *function                                                = "libfsapfs_extended_attribute_get_utf8_name_size";
826 	int result                                                           = 1;
827 
828 	if( extended_attribute == NULL )
829 	{
830 		libcerror_error_set(
831 		 error,
832 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
833 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
834 		 "%s: invalid extended attribute.",
835 		 function );
836 
837 		return( -1 );
838 	}
839 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
840 
841 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
842 	if( libcthreads_read_write_lock_grab_for_read(
843 	     internal_extended_attribute->read_write_lock,
844 	     error ) != 1 )
845 	{
846 		libcerror_error_set(
847 		 error,
848 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
849 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
850 		 "%s: unable to grab read/write lock for reading.",
851 		 function );
852 
853 		return( -1 );
854 	}
855 #endif
856 	if( libuna_utf8_string_size_from_utf8_stream(
857 	     internal_extended_attribute->name,
858 	     (size_t) internal_extended_attribute->name_size,
859 	     utf8_string_size,
860 	     error ) != 1 )
861 	{
862 		libcerror_error_set(
863 		 error,
864 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
865 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
866 		 "%s: unable to retrieve UTF-8 string size.",
867 		 function );
868 
869 		result = -1;
870 	}
871 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
872 	if( libcthreads_read_write_lock_release_for_read(
873 	     internal_extended_attribute->read_write_lock,
874 	     error ) != 1 )
875 	{
876 		libcerror_error_set(
877 		 error,
878 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
879 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
880 		 "%s: unable to release read/write lock for reading.",
881 		 function );
882 
883 		return( -1 );
884 	}
885 #endif
886 	return( result );
887 }
888 
889 /* Retrieves the UTF-8 encoded name
890  * The size should include the end of string character
891  * Returns 1 if successful or -1 on error
892  */
libfsapfs_extended_attribute_get_utf8_name(libfsapfs_extended_attribute_t * extended_attribute,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)893 int libfsapfs_extended_attribute_get_utf8_name(
894      libfsapfs_extended_attribute_t *extended_attribute,
895      uint8_t *utf8_string,
896      size_t utf8_string_size,
897      libcerror_error_t **error )
898 {
899 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
900 	static char *function                                                = "libfsapfs_extended_attribute_get_utf8_name";
901 	int result                                                           = 1;
902 
903 	if( extended_attribute == NULL )
904 	{
905 		libcerror_error_set(
906 		 error,
907 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
908 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
909 		 "%s: invalid extended attribute.",
910 		 function );
911 
912 		return( -1 );
913 	}
914 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
915 
916 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
917 	if( libcthreads_read_write_lock_grab_for_read(
918 	     internal_extended_attribute->read_write_lock,
919 	     error ) != 1 )
920 	{
921 		libcerror_error_set(
922 		 error,
923 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
924 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
925 		 "%s: unable to grab read/write lock for reading.",
926 		 function );
927 
928 		return( -1 );
929 	}
930 #endif
931 	if( libuna_utf8_string_copy_from_utf8_stream(
932 	     utf8_string,
933 	     utf8_string_size,
934 	     internal_extended_attribute->name,
935 	     (size_t) internal_extended_attribute->name_size,
936 	     error ) != 1 )
937 	{
938 		libcerror_error_set(
939 		 error,
940 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
941 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
942 		 "%s: unable to retrieve UTF-8 string.",
943 		 function );
944 
945 		result = -1;
946 	}
947 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
948 	if( libcthreads_read_write_lock_release_for_read(
949 	     internal_extended_attribute->read_write_lock,
950 	     error ) != 1 )
951 	{
952 		libcerror_error_set(
953 		 error,
954 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
955 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
956 		 "%s: unable to release read/write lock for reading.",
957 		 function );
958 
959 		return( -1 );
960 	}
961 #endif
962 	return( result );
963 }
964 
965 /* Compares an UTF-8 string with an extended attribute name
966  * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
967  */
libfsapfs_extended_attribute_compare_name_with_utf8_string(libfsapfs_extended_attribute_t * extended_attribute,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)968 int libfsapfs_extended_attribute_compare_name_with_utf8_string(
969      libfsapfs_extended_attribute_t *extended_attribute,
970      const uint8_t *utf8_string,
971      size_t utf8_string_length,
972      libcerror_error_t **error )
973 {
974 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
975 	static char *function                                                = "libfsapfs_extended_attribute_compare_name_with_utf8_string";
976 	int result                                                           = 0;
977 
978 	if( extended_attribute == NULL )
979 	{
980 		libcerror_error_set(
981 		 error,
982 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
983 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
984 		 "%s: invalid extended attribute.",
985 		 function );
986 
987 		return( -1 );
988 	}
989 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
990 
991 	if( internal_extended_attribute->name != NULL )
992 	{
993 		result = libuna_utf8_string_compare_with_utf8_stream(
994 		          utf8_string,
995 		          utf8_string_length,
996 		          internal_extended_attribute->name,
997 		          internal_extended_attribute->name_size,
998 		          error );
999 
1000 		if( result == -1 )
1001 		{
1002 			libcerror_error_set(
1003 			 error,
1004 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1005 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1006 			 "%s: unable to compare UTF-8 string with name.",
1007 			 function );
1008 
1009 			return( -1 );
1010 		}
1011 	}
1012 	return( result );
1013 }
1014 
1015 /* Retrieves the size of the UTF-16 encoded name
1016  * The returned size includes the end of string character
1017  * Returns 1 if successful or -1 on error
1018  */
libfsapfs_extended_attribute_get_utf16_name_size(libfsapfs_extended_attribute_t * extended_attribute,size_t * utf16_string_size,libcerror_error_t ** error)1019 int libfsapfs_extended_attribute_get_utf16_name_size(
1020      libfsapfs_extended_attribute_t *extended_attribute,
1021      size_t *utf16_string_size,
1022      libcerror_error_t **error )
1023 {
1024 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1025 	static char *function                                                = "libfsapfs_extended_attribute_get_utf16_name_size";
1026 	int result                                                           = 1;
1027 
1028 	if( extended_attribute == NULL )
1029 	{
1030 		libcerror_error_set(
1031 		 error,
1032 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1033 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1034 		 "%s: invalid extended attribute.",
1035 		 function );
1036 
1037 		return( -1 );
1038 	}
1039 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1040 
1041 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1042 	if( libcthreads_read_write_lock_grab_for_read(
1043 	     internal_extended_attribute->read_write_lock,
1044 	     error ) != 1 )
1045 	{
1046 		libcerror_error_set(
1047 		 error,
1048 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1049 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1050 		 "%s: unable to grab read/write lock for reading.",
1051 		 function );
1052 
1053 		return( -1 );
1054 	}
1055 #endif
1056 	if( libuna_utf16_string_size_from_utf8_stream(
1057 	     internal_extended_attribute->name,
1058 	     (size_t) internal_extended_attribute->name_size,
1059 	     utf16_string_size,
1060 	     error ) != 1 )
1061 	{
1062 		libcerror_error_set(
1063 		 error,
1064 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1065 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1066 		 "%s: unable to retrieve UTF-16 string size.",
1067 		 function );
1068 
1069 		result = -1;
1070 	}
1071 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1072 	if( libcthreads_read_write_lock_release_for_read(
1073 	     internal_extended_attribute->read_write_lock,
1074 	     error ) != 1 )
1075 	{
1076 		libcerror_error_set(
1077 		 error,
1078 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1079 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1080 		 "%s: unable to release read/write lock for reading.",
1081 		 function );
1082 
1083 		return( -1 );
1084 	}
1085 #endif
1086 	return( result );
1087 }
1088 
1089 /* Retrieves the UTF-16 encoded name
1090  * The size should include the end of string character
1091  * Returns 1 if successful or -1 on error
1092  */
libfsapfs_extended_attribute_get_utf16_name(libfsapfs_extended_attribute_t * extended_attribute,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)1093 int libfsapfs_extended_attribute_get_utf16_name(
1094      libfsapfs_extended_attribute_t *extended_attribute,
1095      uint16_t *utf16_string,
1096      size_t utf16_string_size,
1097      libcerror_error_t **error )
1098 {
1099 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1100 	static char *function                                                = "libfsapfs_extended_attribute_get_utf16_name";
1101 	int result                                                           = 1;
1102 
1103 	if( extended_attribute == NULL )
1104 	{
1105 		libcerror_error_set(
1106 		 error,
1107 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1108 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1109 		 "%s: invalid extended attribute.",
1110 		 function );
1111 
1112 		return( -1 );
1113 	}
1114 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1115 
1116 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1117 	if( libcthreads_read_write_lock_grab_for_read(
1118 	     internal_extended_attribute->read_write_lock,
1119 	     error ) != 1 )
1120 	{
1121 		libcerror_error_set(
1122 		 error,
1123 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1124 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1125 		 "%s: unable to grab read/write lock for reading.",
1126 		 function );
1127 
1128 		return( -1 );
1129 	}
1130 #endif
1131 	if( libuna_utf16_string_copy_from_utf8_stream(
1132 	     utf16_string,
1133 	     utf16_string_size,
1134 	     internal_extended_attribute->name,
1135 	     (size_t) internal_extended_attribute->name_size,
1136 	     error ) != 1 )
1137 	{
1138 		libcerror_error_set(
1139 		 error,
1140 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1141 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1142 		 "%s: unable to retrieve UTF-16 string.",
1143 		 function );
1144 
1145 		result = -1;
1146 	}
1147 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1148 	if( libcthreads_read_write_lock_release_for_read(
1149 	     internal_extended_attribute->read_write_lock,
1150 	     error ) != 1 )
1151 	{
1152 		libcerror_error_set(
1153 		 error,
1154 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1155 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1156 		 "%s: unable to release read/write lock for reading.",
1157 		 function );
1158 
1159 		return( -1 );
1160 	}
1161 #endif
1162 	return( result );
1163 }
1164 
1165 /* Compares an UTF-16 string with an extended attribute name
1166  * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
1167  */
libfsapfs_extended_attribute_compare_name_with_utf16_string(libfsapfs_extended_attribute_t * extended_attribute,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)1168 int libfsapfs_extended_attribute_compare_name_with_utf16_string(
1169      libfsapfs_extended_attribute_t *extended_attribute,
1170      const uint16_t *utf16_string,
1171      size_t utf16_string_length,
1172      libcerror_error_t **error )
1173 {
1174 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1175 	static char *function                                                = "libfsapfs_extended_attribute_compare_name_with_utf16_string";
1176 	int result                                                           = 0;
1177 
1178 	if( extended_attribute == NULL )
1179 	{
1180 		libcerror_error_set(
1181 		 error,
1182 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1183 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1184 		 "%s: invalid extended attribute.",
1185 		 function );
1186 
1187 		return( -1 );
1188 	}
1189 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1190 
1191 	if( internal_extended_attribute->name != NULL )
1192 	{
1193 		result = libuna_utf16_string_compare_with_utf8_stream(
1194 		          utf16_string,
1195 		          utf16_string_length,
1196 		          internal_extended_attribute->name,
1197 		          internal_extended_attribute->name_size,
1198 		          error );
1199 
1200 		if( result == -1 )
1201 		{
1202 			libcerror_error_set(
1203 			 error,
1204 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1205 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1206 			 "%s: unable to compare UTF-16 string with name.",
1207 			 function );
1208 
1209 			return( -1 );
1210 		}
1211 	}
1212 	return( result );
1213 }
1214 
1215 /* Determines the file extents
1216  * Returns 1 if successful or -1 on error
1217  */
libfsapfs_internal_extended_attribute_get_file_extents(libfsapfs_internal_extended_attribute_t * internal_extended_attribute,libcerror_error_t ** error)1218 int libfsapfs_internal_extended_attribute_get_file_extents(
1219      libfsapfs_internal_extended_attribute_t *internal_extended_attribute,
1220      libcerror_error_t **error )
1221 {
1222 	static char *function = "libfsapfs_internal_extended_attribute_get_file_extents";
1223 	int result            = 0;
1224 
1225 	if( internal_extended_attribute == NULL )
1226 	{
1227 		libcerror_error_set(
1228 		 error,
1229 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1230 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1231 		 "%s: invalid extended attribute.",
1232 		 function );
1233 
1234 		return( -1 );
1235 	}
1236 	if( internal_extended_attribute->file_extents != NULL )
1237 	{
1238 		libcerror_error_set(
1239 		 error,
1240 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1241 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1242 		 "%s: invalid extended attribute - file extents value already set.",
1243 		 function );
1244 
1245 		return( -1 );
1246 	}
1247 	if( libcdata_array_initialize(
1248 	     &( internal_extended_attribute->file_extents ),
1249 	     0,
1250 	     error ) != 1 )
1251 	{
1252 		libcerror_error_set(
1253 		 error,
1254 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1255 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1256 		 "%s: unable to create file extents array.",
1257 		 function );
1258 
1259 		goto on_error;
1260 	}
1261 	result = libfsapfs_file_system_btree_get_file_extents(
1262 		  internal_extended_attribute->file_system_btree,
1263 		  internal_extended_attribute->file_io_handle,
1264 		  internal_extended_attribute->data_stream_identifier,
1265 		  internal_extended_attribute->file_extents,
1266 		  error );
1267 
1268 	if( result == -1 )
1269 	{
1270 		libcerror_error_set(
1271 		 error,
1272 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1273 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1274 		 "%s: unable to retrieve file extents from file system B-tree.",
1275 		 function );
1276 
1277 		goto on_error;
1278 	}
1279 	return( 1 );
1280 
1281 on_error:
1282 	if( internal_extended_attribute->file_extents != NULL )
1283 	{
1284 		libcdata_array_free(
1285 		 &( internal_extended_attribute->file_extents ),
1286 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_extent_free,
1287 		 NULL );
1288 	}
1289 	return( -1 );
1290 }
1291 
1292 /* Determines the data stream
1293  * Returns 1 if successful or -1 on error
1294  */
libfsapfs_internal_extended_attribute_get_data_stream(libfsapfs_internal_extended_attribute_t * internal_extended_attribute,libcerror_error_t ** error)1295 int libfsapfs_internal_extended_attribute_get_data_stream(
1296      libfsapfs_internal_extended_attribute_t *internal_extended_attribute,
1297      libcerror_error_t **error )
1298 {
1299 	static char *function = "libfsapfs_internal_extended_attribute_get_data_stream";
1300 
1301 	if( internal_extended_attribute == NULL )
1302 	{
1303 		libcerror_error_set(
1304 		 error,
1305 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1306 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1307 		 "%s: invalid extended attribute.",
1308 		 function );
1309 
1310 		return( -1 );
1311 	}
1312 	if( internal_extended_attribute->io_handle == NULL )
1313 	{
1314 		libcerror_error_set(
1315 		 error,
1316 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1317 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1318 		 "%s: invalid internal extended attribute - missing IO handle.",
1319 		 function );
1320 
1321 		return( -1 );
1322 	}
1323 	if( internal_extended_attribute->data_stream != NULL )
1324 	{
1325 		libcerror_error_set(
1326 		 error,
1327 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1328 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1329 		 "%s: invalid extended attribute - data stream value already set.",
1330 		 function );
1331 
1332 		return( -1 );
1333 	}
1334 	if( internal_extended_attribute->data != NULL )
1335 	{
1336 		if( libfsapfs_data_stream_initialize_from_data(
1337 		     &( internal_extended_attribute->data_stream ),
1338 		     internal_extended_attribute->data,
1339 		     internal_extended_attribute->data_stream_size,
1340 		     error ) != 1 )
1341 		{
1342 			libcerror_error_set(
1343 			 error,
1344 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1346 			 "%s: unable to create data stream from data.",
1347 			 function );
1348 
1349 			goto on_error;
1350 		}
1351 	}
1352 	else
1353 	{
1354 		if( internal_extended_attribute->file_extents == NULL )
1355 		{
1356 			if( libfsapfs_internal_extended_attribute_get_file_extents(
1357 			     internal_extended_attribute,
1358 			     error ) != 1 )
1359 			{
1360 				libcerror_error_set(
1361 				 error,
1362 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1363 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1364 				 "%s: unable to determine file extents.",
1365 				 function );
1366 
1367 				goto on_error;
1368 			}
1369 		}
1370 		if( libfsapfs_data_stream_initialize_from_file_extents(
1371 		     &( internal_extended_attribute->data_stream ),
1372 		     internal_extended_attribute->io_handle,
1373 		     internal_extended_attribute->encryption_context,
1374 		     internal_extended_attribute->file_extents,
1375 		     internal_extended_attribute->data_stream_size,
1376 		     0,
1377 		     error ) != 1 )
1378 		{
1379 			libcerror_error_set(
1380 			 error,
1381 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1382 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1383 			 "%s: unable to create data stream from file extents.",
1384 			 function );
1385 
1386 			goto on_error;
1387 		}
1388 	}
1389 	return( 1 );
1390 
1391 on_error:
1392 	if( internal_extended_attribute->data_stream != NULL )
1393 	{
1394 		libfdata_stream_free(
1395 		 &( internal_extended_attribute->data_stream ),
1396 		 NULL );
1397 	}
1398 	return( -1 );
1399 }
1400 
1401 /* Reads data at the current offset into a buffer
1402  * Returns the number of bytes read or -1 on error
1403  */
libfsapfs_extended_attribute_read_buffer(libfsapfs_extended_attribute_t * extended_attribute,void * buffer,size_t buffer_size,libcerror_error_t ** error)1404 ssize_t libfsapfs_extended_attribute_read_buffer(
1405          libfsapfs_extended_attribute_t *extended_attribute,
1406          void *buffer,
1407          size_t buffer_size,
1408          libcerror_error_t **error )
1409 {
1410 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1411 	static char *function                                                = "libfsapfs_extended_attribute_read_buffer";
1412 	ssize_t read_count                                                   = 0;
1413 
1414 	if( extended_attribute == NULL )
1415 	{
1416 		libcerror_error_set(
1417 		 error,
1418 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1419 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1420 		 "%s: invalid extended attribute.",
1421 		 function );
1422 
1423 		return( -1 );
1424 	}
1425 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1426 
1427 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1428 	if( libcthreads_read_write_lock_grab_for_write(
1429 	     internal_extended_attribute->read_write_lock,
1430 	     error ) != 1 )
1431 	{
1432 		libcerror_error_set(
1433 		 error,
1434 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1435 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1436 		 "%s: unable to grab read/write lock for writing.",
1437 		 function );
1438 
1439 		return( -1 );
1440 	}
1441 #endif
1442 	if( internal_extended_attribute->data_stream == NULL )
1443 	{
1444 		if( libfsapfs_internal_extended_attribute_get_data_stream(
1445 		     internal_extended_attribute,
1446 		     error ) != 1 )
1447 		{
1448 			libcerror_error_set(
1449 			 error,
1450 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1451 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1452 			 "%s: unable to determine data stream.",
1453 			 function );
1454 
1455 			goto on_error;
1456 		}
1457 	}
1458 	read_count = libfdata_stream_read_buffer(
1459 	              internal_extended_attribute->data_stream,
1460 	              (intptr_t *) internal_extended_attribute->file_io_handle,
1461 	              (uint8_t *) buffer,
1462 	              buffer_size,
1463 	              0,
1464 	              error );
1465 
1466 	if( read_count < 0 )
1467 	{
1468 		libcerror_error_set(
1469 		 error,
1470 		 LIBCERROR_ERROR_DOMAIN_IO,
1471 		 LIBCERROR_IO_ERROR_READ_FAILED,
1472 		 "%s: unable to read buffer from data stream.",
1473 		 function );
1474 
1475 		goto on_error;
1476 	}
1477 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1478 	if( libcthreads_read_write_lock_release_for_write(
1479 	     internal_extended_attribute->read_write_lock,
1480 	     error ) != 1 )
1481 	{
1482 		libcerror_error_set(
1483 		 error,
1484 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1485 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1486 		 "%s: unable to release read/write lock for writing.",
1487 		 function );
1488 
1489 		return( -1 );
1490 	}
1491 #endif
1492 	return( read_count );
1493 
1494 on_error:
1495 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1496 	libcthreads_read_write_lock_release_for_write(
1497 	 internal_extended_attribute->read_write_lock,
1498 	 NULL );
1499 #endif
1500 	return( -1 );
1501 }
1502 
1503 /* Reads data at a specific offset
1504  * Returns the number of bytes read or -1 on error
1505  */
libfsapfs_extended_attribute_read_buffer_at_offset(libfsapfs_extended_attribute_t * extended_attribute,void * buffer,size_t buffer_size,off64_t offset,libcerror_error_t ** error)1506 ssize_t libfsapfs_extended_attribute_read_buffer_at_offset(
1507          libfsapfs_extended_attribute_t *extended_attribute,
1508          void *buffer,
1509          size_t buffer_size,
1510          off64_t offset,
1511          libcerror_error_t **error )
1512 {
1513 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1514 	static char *function                                                = "libfsapfs_extended_attribute_read_buffer_at_offset";
1515 	ssize_t read_count                                                   = 0;
1516 
1517 	if( extended_attribute == NULL )
1518 	{
1519 		libcerror_error_set(
1520 		 error,
1521 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1522 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1523 		 "%s: invalid extended attribute.",
1524 		 function );
1525 
1526 		return( -1 );
1527 	}
1528 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1529 
1530 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1531 	if( libcthreads_read_write_lock_grab_for_write(
1532 	     internal_extended_attribute->read_write_lock,
1533 	     error ) != 1 )
1534 	{
1535 		libcerror_error_set(
1536 		 error,
1537 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1538 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1539 		 "%s: unable to grab read/write lock for writing.",
1540 		 function );
1541 
1542 		return( -1 );
1543 	}
1544 #endif
1545 	if( internal_extended_attribute->data_stream == NULL )
1546 	{
1547 		if( libfsapfs_internal_extended_attribute_get_data_stream(
1548 		     internal_extended_attribute,
1549 		     error ) != 1 )
1550 		{
1551 			libcerror_error_set(
1552 			 error,
1553 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1554 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1555 			 "%s: unable to determine data stream.",
1556 			 function );
1557 
1558 			goto on_error;
1559 		}
1560 	}
1561 	read_count = libfdata_stream_read_buffer_at_offset(
1562 	              internal_extended_attribute->data_stream,
1563 	              (intptr_t *) internal_extended_attribute->file_io_handle,
1564 	              (uint8_t *) buffer,
1565 	              buffer_size,
1566 	              offset,
1567 	              0,
1568 	              error );
1569 
1570 	if( read_count < 0 )
1571 	{
1572 		libcerror_error_set(
1573 		 error,
1574 		 LIBCERROR_ERROR_DOMAIN_IO,
1575 		 LIBCERROR_IO_ERROR_READ_FAILED,
1576 		 "%s: unable to read buffer at offset from data stream.",
1577 		 function );
1578 
1579 		goto on_error;
1580 	}
1581 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1582 	if( libcthreads_read_write_lock_release_for_write(
1583 	     internal_extended_attribute->read_write_lock,
1584 	     error ) != 1 )
1585 	{
1586 		libcerror_error_set(
1587 		 error,
1588 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1589 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1590 		 "%s: unable to release read/write lock for writing.",
1591 		 function );
1592 
1593 		return( -1 );
1594 	}
1595 #endif
1596 	return( read_count );
1597 
1598 on_error:
1599 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1600 	libcthreads_read_write_lock_release_for_write(
1601 	 internal_extended_attribute->read_write_lock,
1602 	 NULL );
1603 #endif
1604 	return( -1 );
1605 }
1606 
1607 /* Seeks a certain offset
1608  * Returns the offset if seek is successful or -1 on error
1609  */
libfsapfs_extended_attribute_seek_offset(libfsapfs_extended_attribute_t * extended_attribute,off64_t offset,int whence,libcerror_error_t ** error)1610 off64_t libfsapfs_extended_attribute_seek_offset(
1611          libfsapfs_extended_attribute_t *extended_attribute,
1612          off64_t offset,
1613          int whence,
1614          libcerror_error_t **error )
1615 {
1616 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1617 	static char *function                                                = "libfsapfs_extended_attribute_seek_offset";
1618 
1619 	if( extended_attribute == NULL )
1620 	{
1621 		libcerror_error_set(
1622 		 error,
1623 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1624 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1625 		 "%s: invalid extended attribute.",
1626 		 function );
1627 
1628 		return( -1 );
1629 	}
1630 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1631 
1632 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1633 	if( libcthreads_read_write_lock_grab_for_write(
1634 	     internal_extended_attribute->read_write_lock,
1635 	     error ) != 1 )
1636 	{
1637 		libcerror_error_set(
1638 		 error,
1639 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1640 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1641 		 "%s: unable to grab read/write lock for writing.",
1642 		 function );
1643 
1644 		return( -1 );
1645 	}
1646 #endif
1647 	if( internal_extended_attribute->data_stream == NULL )
1648 	{
1649 		if( libfsapfs_internal_extended_attribute_get_data_stream(
1650 		     internal_extended_attribute,
1651 		     error ) != 1 )
1652 		{
1653 			libcerror_error_set(
1654 			 error,
1655 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1656 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1657 			 "%s: unable to determine data stream.",
1658 			 function );
1659 
1660 			goto on_error;
1661 		}
1662 	}
1663 	offset = libfdata_stream_seek_offset(
1664 	          internal_extended_attribute->data_stream,
1665 	          offset,
1666 	          whence,
1667 	          error );
1668 
1669 	if( offset < 0 )
1670 	{
1671 		libcerror_error_set(
1672 		 error,
1673 		 LIBCERROR_ERROR_DOMAIN_IO,
1674 		 LIBCERROR_IO_ERROR_SEEK_FAILED,
1675 		 "%s: unable to seek offset in data stream.",
1676 		 function );
1677 
1678 		goto on_error;
1679 	}
1680 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1681 	if( libcthreads_read_write_lock_release_for_write(
1682 	     internal_extended_attribute->read_write_lock,
1683 	     error ) != 1 )
1684 	{
1685 		libcerror_error_set(
1686 		 error,
1687 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1688 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1689 		 "%s: unable to release read/write lock for writing.",
1690 		 function );
1691 
1692 		return( -1 );
1693 	}
1694 #endif
1695 	return( offset );
1696 
1697 on_error:
1698 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1699 	libcthreads_read_write_lock_release_for_write(
1700 	 internal_extended_attribute->read_write_lock,
1701 	 NULL );
1702 #endif
1703 	return( -1 );
1704 }
1705 
1706 /* Retrieves the current offset
1707  * Returns the offset if successful or -1 on error
1708  */
libfsapfs_extended_attribute_get_offset(libfsapfs_extended_attribute_t * extended_attribute,off64_t * offset,libcerror_error_t ** error)1709 int libfsapfs_extended_attribute_get_offset(
1710      libfsapfs_extended_attribute_t *extended_attribute,
1711      off64_t *offset,
1712      libcerror_error_t **error )
1713 {
1714 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1715 	static char *function                                                = "libfsapfs_extended_attribute_get_offset";
1716 	int result                                                           = 1;
1717 
1718 	if( extended_attribute == NULL )
1719 	{
1720 		libcerror_error_set(
1721 		 error,
1722 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1723 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1724 		 "%s: invalid extended attribute.",
1725 		 function );
1726 
1727 		return( -1 );
1728 	}
1729 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1730 
1731 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1732 	if( libcthreads_read_write_lock_grab_for_write(
1733 	     internal_extended_attribute->read_write_lock,
1734 	     error ) != 1 )
1735 	{
1736 		libcerror_error_set(
1737 		 error,
1738 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1739 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1740 		 "%s: unable to grab read/write lock for writing.",
1741 		 function );
1742 
1743 		return( -1 );
1744 	}
1745 #endif
1746 	if( internal_extended_attribute->data_stream == NULL )
1747 	{
1748 		if( libfsapfs_internal_extended_attribute_get_data_stream(
1749 		     internal_extended_attribute,
1750 		     error ) != 1 )
1751 		{
1752 			libcerror_error_set(
1753 			 error,
1754 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1755 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1756 			 "%s: unable to determine data stream.",
1757 			 function );
1758 
1759 			goto on_error;
1760 		}
1761 	}
1762 	if( libfdata_stream_get_offset(
1763 	     internal_extended_attribute->data_stream,
1764 	     offset,
1765 	     error ) != 1 )
1766 	{
1767 		libcerror_error_set(
1768 		 error,
1769 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1771 		 "%s: unable to retrieve offset from data stream.",
1772 		 function );
1773 
1774 		goto on_error;
1775 	}
1776 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1777 	if( libcthreads_read_write_lock_release_for_write(
1778 	     internal_extended_attribute->read_write_lock,
1779 	     error ) != 1 )
1780 	{
1781 		libcerror_error_set(
1782 		 error,
1783 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1784 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1785 		 "%s: unable to release read/write lock for writing.",
1786 		 function );
1787 
1788 		return( -1 );
1789 	}
1790 #endif
1791 	return( result );
1792 
1793 on_error:
1794 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1795 	libcthreads_read_write_lock_release_for_write(
1796 	 internal_extended_attribute->read_write_lock,
1797 	 NULL );
1798 #endif
1799 	return( -1 );
1800 }
1801 
1802 /* Retrieves the size of the data stream object
1803  * Returns 1 if successful or -1 on error
1804  */
libfsapfs_extended_attribute_get_size(libfsapfs_extended_attribute_t * extended_attribute,size64_t * size,libcerror_error_t ** error)1805 int libfsapfs_extended_attribute_get_size(
1806      libfsapfs_extended_attribute_t *extended_attribute,
1807      size64_t *size,
1808      libcerror_error_t **error )
1809 {
1810 	libfsapfs_internal_extended_attribute_t *internal_extended_attribute = NULL;
1811 	static char *function                                                = "libfsapfs_extended_attribute_get_size";
1812 
1813 	if( extended_attribute == NULL )
1814 	{
1815 		libcerror_error_set(
1816 		 error,
1817 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1818 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1819 		 "%s: invalid extended attribute.",
1820 		 function );
1821 
1822 		return( -1 );
1823 	}
1824 	internal_extended_attribute = (libfsapfs_internal_extended_attribute_t *) extended_attribute;
1825 
1826 	if( size == NULL )
1827 	{
1828 		libcerror_error_set(
1829 		 error,
1830 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1831 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1832 		 "%s: invalid size.",
1833 		 function );
1834 
1835 		return( -1 );
1836 	}
1837 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1838 	if( libcthreads_read_write_lock_grab_for_write(
1839 	     internal_extended_attribute->read_write_lock,
1840 	     error ) != 1 )
1841 	{
1842 		libcerror_error_set(
1843 		 error,
1844 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1845 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1846 		 "%s: unable to grab read/write lock for writing.",
1847 		 function );
1848 
1849 		return( -1 );
1850 	}
1851 #endif
1852 	*size = internal_extended_attribute->data_stream_size;
1853 
1854 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1855 	if( libcthreads_read_write_lock_release_for_write(
1856 	     internal_extended_attribute->read_write_lock,
1857 	     error ) != 1 )
1858 	{
1859 		libcerror_error_set(
1860 		 error,
1861 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1862 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1863 		 "%s: unable to release read/write lock for writing.",
1864 		 function );
1865 
1866 		return( -1 );
1867 	}
1868 #endif
1869 	return( 1 );
1870 }
1871 
1872