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