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