1 /*
2  * Volume 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 <narrow_string.h>
25 #include <types.h>
26 #include <wide_string.h>
27 
28 #include "libfsapfs_container_data_handle.h"
29 #include "libfsapfs_container_key_bag.h"
30 #include "libfsapfs_debug.h"
31 #include "libfsapfs_definitions.h"
32 #include "libfsapfs_encryption_context.h"
33 #include "libfsapfs_extent_reference_tree.h"
34 #include "libfsapfs_file_entry.h"
35 #include "libfsapfs_file_system_btree.h"
36 #include "libfsapfs_file_system_data_handle.h"
37 #include "libfsapfs_inode.h"
38 #include "libfsapfs_io_handle.h"
39 #include "libfsapfs_libbfio.h"
40 #include "libfsapfs_libcerror.h"
41 #include "libfsapfs_libcnotify.h"
42 #include "libfsapfs_libcthreads.h"
43 #include "libfsapfs_libfdata.h"
44 #include "libfsapfs_libuna.h"
45 #include "libfsapfs_object_map.h"
46 #include "libfsapfs_object_map_btree.h"
47 #include "libfsapfs_object_map_descriptor.h"
48 #include "libfsapfs_snapshot.h"
49 #include "libfsapfs_snapshot_metadata.h"
50 #include "libfsapfs_snapshot_metadata_tree.h"
51 #include "libfsapfs_volume.h"
52 #include "libfsapfs_volume_key_bag.h"
53 #include "libfsapfs_volume_superblock.h"
54 
55 /* Creates a volume
56  * Make sure the value volume is referencing, is set to NULL
57  * Returns 1 if successful or -1 on error
58  */
libfsapfs_volume_initialize(libfsapfs_volume_t ** volume,libfsapfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libfsapfs_container_key_bag_t * container_key_bag,libcerror_error_t ** error)59 int libfsapfs_volume_initialize(
60      libfsapfs_volume_t **volume,
61      libfsapfs_io_handle_t *io_handle,
62      libbfio_handle_t *file_io_handle,
63      libfsapfs_container_key_bag_t *container_key_bag,
64      libcerror_error_t **error )
65 {
66 	libfsapfs_internal_volume_t *internal_volume = NULL;
67 	static char *function                        = "libfsapfs_volume_initialize";
68 
69 	if( volume == NULL )
70 	{
71 		libcerror_error_set(
72 		 error,
73 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
74 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
75 		 "%s: invalid volume.",
76 		 function );
77 
78 		return( -1 );
79 	}
80 	if( *volume != NULL )
81 	{
82 		libcerror_error_set(
83 		 error,
84 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
85 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
86 		 "%s: invalid volume value already set.",
87 		 function );
88 
89 		return( -1 );
90 	}
91 	if( io_handle == NULL )
92 	{
93 		libcerror_error_set(
94 		 error,
95 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
96 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
97 		 "%s: invalid IO handle.",
98 		 function );
99 
100 		return( -1 );
101 	}
102 	if( file_io_handle == NULL )
103 	{
104 		libcerror_error_set(
105 		 error,
106 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
107 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
108 		 "%s: invalid file IO handle.",
109 		 function );
110 
111 		return( -1 );
112 	}
113 	internal_volume = memory_allocate_structure(
114 	                   libfsapfs_internal_volume_t );
115 
116 	if( internal_volume == NULL )
117 	{
118 		libcerror_error_set(
119 		 error,
120 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
121 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
122 		 "%s: unable to create volume.",
123 		 function );
124 
125 		goto on_error;
126 	}
127 	if( memory_set(
128 	     internal_volume,
129 	     0,
130 	     sizeof( libfsapfs_internal_volume_t ) ) == NULL )
131 	{
132 		libcerror_error_set(
133 		 error,
134 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
135 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
136 		 "%s: unable to clear volume.",
137 		 function );
138 
139 		goto on_error;
140 	}
141 /* TODO clone file_io_handle? */
142 	internal_volume->io_handle         = io_handle;
143 	internal_volume->file_io_handle    = file_io_handle;
144 	internal_volume->container_key_bag = container_key_bag;
145 	internal_volume->is_locked         = 1;
146 
147 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
148 	if( libcthreads_read_write_lock_initialize(
149 	     &( internal_volume->read_write_lock ),
150 	     error ) != 1 )
151 	{
152 		libcerror_error_set(
153 		 error,
154 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
155 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
156 		 "%s: unable to initialize read/write lock.",
157 		 function );
158 
159 		goto on_error;
160 	}
161 #endif
162 	*volume = (libfsapfs_volume_t *) internal_volume;
163 
164 	return( 1 );
165 
166 on_error:
167 	if( internal_volume != NULL )
168 	{
169 		memory_free(
170 		 internal_volume );
171 	}
172 	return( -1 );
173 }
174 
175 /* Frees a volume
176  * Returns 1 if successful or -1 on error
177  */
libfsapfs_volume_free(libfsapfs_volume_t ** volume,libcerror_error_t ** error)178 int libfsapfs_volume_free(
179      libfsapfs_volume_t **volume,
180      libcerror_error_t **error )
181 {
182 	libfsapfs_internal_volume_t *internal_volume = NULL;
183 	static char *function                        = "libfsapfs_volume_free";
184 	int result                                   = 1;
185 
186 	if( volume == NULL )
187 	{
188 		libcerror_error_set(
189 		 error,
190 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
191 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
192 		 "%s: invalid volume.",
193 		 function );
194 
195 		return( -1 );
196 	}
197 	if( *volume != NULL )
198 	{
199 		internal_volume = (libfsapfs_internal_volume_t *) *volume;
200 		*volume         = NULL;
201 
202 		if( internal_volume->file_io_handle != NULL )
203 		{
204 			if( libfsapfs_internal_volume_close(
205 			     internal_volume,
206 			     error ) != 0 )
207 			{
208 				libcerror_error_set(
209 				 error,
210 				 LIBCERROR_ERROR_DOMAIN_IO,
211 				 LIBCERROR_IO_ERROR_CLOSE_FAILED,
212 				 "%s: unable to close volume.",
213 				 function );
214 
215 				result = -1;
216 			}
217 		}
218 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
219 		if( libcthreads_read_write_lock_free(
220 		     &( internal_volume->read_write_lock ),
221 		     error ) != 1 )
222 		{
223 			libcerror_error_set(
224 			 error,
225 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
226 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
227 			 "%s: unable to free read/write lock.",
228 			 function );
229 
230 			result = -1;
231 		}
232 #endif
233 		memory_free(
234 		 internal_volume );
235 	}
236 	return( result );
237 }
238 
239 /* Opens a volume for reading
240  * Returns 1 if successful or -1 on error
241  */
libfsapfs_internal_volume_open_read(libfsapfs_internal_volume_t * internal_volume,libbfio_handle_t * file_io_handle,off64_t file_offset,libcerror_error_t ** error)242 int libfsapfs_internal_volume_open_read(
243      libfsapfs_internal_volume_t *internal_volume,
244      libbfio_handle_t *file_io_handle,
245      off64_t file_offset,
246      libcerror_error_t **error )
247 {
248 	libfsapfs_container_data_handle_t *container_data_handle     = NULL;
249 	libfsapfs_file_system_data_handle_t *file_system_data_handle = NULL;
250 	libfsapfs_object_map_t *object_map                           = NULL;
251 	static char *function                                        = "libfsapfs_internal_volume_open_read";
252 	uint64_t key_bag_block_number                                = 0;
253 	uint64_t key_bag_number_of_blocks                            = 0;
254 	int element_index                                            = 0;
255 	int result                                                   = 0;
256 
257 #if defined( HAVE_DEBUG_OUTPUT )
258 	libfsapfs_extent_reference_tree_t *extent_reference_tree     = NULL;
259 #endif
260 
261 	if( internal_volume == NULL )
262 	{
263 		libcerror_error_set(
264 		 error,
265 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
266 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
267 		 "%s: invalid volume.",
268 		 function );
269 
270 		return( -1 );
271 	}
272 	if( internal_volume->io_handle == NULL )
273 	{
274 		libcerror_error_set(
275 		 error,
276 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
277 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
278 		 "%s: invalid volume - missing IO handle.",
279 		 function );
280 
281 		return( -1 );
282 	}
283 	if( internal_volume->superblock != NULL )
284 	{
285 		libcerror_error_set(
286 		 error,
287 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
288 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
289 		 "%s: invalid volume - superblock map value already set.",
290 		 function );
291 
292 		return( -1 );
293 	}
294 	if( internal_volume->container_data_block_vector != NULL )
295 	{
296 		libcerror_error_set(
297 		 error,
298 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
299 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
300 		 "%s: invalid volume - container data block vector value already set.",
301 		 function );
302 
303 		return( -1 );
304 	}
305 	if( internal_volume->object_map_btree != NULL )
306 	{
307 		libcerror_error_set(
308 		 error,
309 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
310 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
311 		 "%s: invalid volume - object map B-tree value already set.",
312 		 function );
313 
314 		return( -1 );
315 	}
316 	if( internal_volume->snapshot_metadata_tree != NULL )
317 	{
318 		libcerror_error_set(
319 		 error,
320 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
321 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
322 		 "%s: invalid volume - snapshot metadata tree value already set.",
323 		 function );
324 
325 		return( -1 );
326 	}
327 	if( internal_volume->key_bag != NULL )
328 	{
329 		libcerror_error_set(
330 		 error,
331 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
332 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
333 		 "%s: invalid volume - key bag value already set.",
334 		 function );
335 
336 		return( -1 );
337 	}
338 	if( internal_volume->encryption_context != NULL )
339 	{
340 		libcerror_error_set(
341 		 error,
342 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
343 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
344 		 "%s: invalid volume - encryption context value already set.",
345 		 function );
346 
347 		return( -1 );
348 	}
349 	if( internal_volume->file_system_data_block_vector != NULL )
350 	{
351 		libcerror_error_set(
352 		 error,
353 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
354 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
355 		 "%s: invalid volume - file system data block vector value already set.",
356 		 function );
357 
358 		return( -1 );
359 	}
360 #if defined( HAVE_DEBUG_OUTPUT )
361 	if( libcnotify_verbose != 0 )
362 	{
363 		libcnotify_printf(
364 		 "Reading volume superblock:\n" );
365 	}
366 #endif
367 	if( libfsapfs_volume_superblock_initialize(
368 	     &( internal_volume->superblock ),
369 	     error ) != 1 )
370 	{
371 		libcerror_error_set(
372 		 error,
373 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
374 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
375 		 "%s: unable to create volume superblock.",
376 		 function );
377 
378 		goto on_error;
379 	}
380 	if( libfsapfs_volume_superblock_read_file_io_handle(
381 	     internal_volume->superblock,
382 	     file_io_handle,
383 	     file_offset,
384 	     error ) != 1 )
385 	{
386 		libcerror_error_set(
387 		 error,
388 		 LIBCERROR_ERROR_DOMAIN_IO,
389 		 LIBCERROR_IO_ERROR_READ_FAILED,
390 		 "%s: unable to read volume superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
391 		 function,
392 		 file_offset,
393 		 file_offset );
394 
395 		goto on_error;
396 	}
397 	if( libfsapfs_container_data_handle_initialize(
398 	     &container_data_handle,
399 	     internal_volume->io_handle,
400 	     error ) != 1 )
401 	{
402 		libcerror_error_set(
403 		 error,
404 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
405 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
406 		 "%s: unable to create container data handle.",
407 		 function );
408 
409 		goto on_error;
410 	}
411 	if( libfdata_vector_initialize(
412 	     &( internal_volume->container_data_block_vector ),
413 	     (size64_t) internal_volume->io_handle->block_size,
414 	     (intptr_t *) container_data_handle,
415 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_container_data_handle_free,
416 	     NULL,
417 	     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsapfs_container_data_handle_read_data_block,
418 	     NULL,
419 	     LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
420 	     error ) != 1 )
421 	{
422 		libcerror_error_set(
423 		 error,
424 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
425 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
426 		 "%s: unable to create container data block vector.",
427 		 function );
428 
429 		goto on_error;
430 	}
431 	internal_volume->container_data_handle = container_data_handle;
432 	container_data_handle                  = NULL;
433 
434 	if( libfdata_vector_append_segment(
435 	     internal_volume->container_data_block_vector,
436 	     &element_index,
437 	     0,
438 	     0,
439 	     internal_volume->io_handle->container_size,
440 	     0,
441 	     error ) != 1 )
442 	{
443 		libcerror_error_set(
444 		 error,
445 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
446 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
447 		 "%s: unable to append segment to container data block vector.",
448 		 function );
449 
450 		goto on_error;
451 	}
452 /* TODO refactor into function to read object map */
453 	if( internal_volume->superblock->object_map_block_number == 0 )
454 	{
455 		libcerror_error_set(
456 		 error,
457 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
458 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
459 		 "%s: missing object map block number.",
460 		 function );
461 
462 		goto on_error;
463 	}
464 #if defined( HAVE_DEBUG_OUTPUT )
465 	if( libcnotify_verbose != 0 )
466 	{
467 		libcnotify_printf(
468 		 "Reading object map:\n" );
469 	}
470 #endif
471 	file_offset = internal_volume->superblock->object_map_block_number * internal_volume->io_handle->block_size;
472 
473 	if( libfsapfs_object_map_initialize(
474 	     &object_map,
475 	     error ) != 1 )
476 	{
477 		libcerror_error_set(
478 		 error,
479 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
480 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
481 		 "%s: unable to create object map.",
482 		 function );
483 
484 		goto on_error;
485 	}
486 	if( libfsapfs_object_map_read_file_io_handle(
487 	     object_map,
488 	     file_io_handle,
489 	     file_offset,
490 	     error ) != 1 )
491 	{
492 		libcerror_error_set(
493 		 error,
494 		 LIBCERROR_ERROR_DOMAIN_IO,
495 		 LIBCERROR_IO_ERROR_READ_FAILED,
496 		 "%s: unable to read object map at offset: %" PRIi64 " (0x%08" PRIx64 ").",
497 		 function,
498 		 file_offset,
499 		 file_offset );
500 
501 		goto on_error;
502 	}
503 	if( object_map->btree_block_number == 0 )
504 	{
505 		libcerror_error_set(
506 		 error,
507 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
508 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
509 		 "%s: missing object map B-tree block number.",
510 		 function );
511 
512 		goto on_error;
513 	}
514 #if defined( HAVE_DEBUG_OUTPUT )
515 	if( libcnotify_verbose != 0 )
516 	{
517 		libcnotify_printf(
518 		 "Reading object map B-tree:\n" );
519 	}
520 #endif
521 	if( libfsapfs_object_map_btree_initialize(
522 	     &( internal_volume->object_map_btree ),
523 	     internal_volume->io_handle,
524 	     internal_volume->container_data_block_vector,
525 	     object_map->btree_block_number,
526 	     error ) != 1 )
527 	{
528 		libcerror_error_set(
529 		 error,
530 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
531 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
532 		 "%s: unable to create object map B-tree.",
533 		 function );
534 
535 		goto on_error;
536 	}
537 	if( libfsapfs_object_map_free(
538 	     &object_map,
539 	     error ) != 1 )
540 	{
541 		libcerror_error_set(
542 		 error,
543 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
544 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
545 		 "%s: unable to free object map.",
546 		 function );
547 
548 		goto on_error;
549 	}
550 	internal_volume->is_locked = 0;
551 
552 	if( ( internal_volume->container_key_bag != NULL )
553 	 && ( ( internal_volume->superblock->volume_flags & 0x00000001UL ) == 0 ) )
554 	{
555 		internal_volume->is_locked = internal_volume->container_key_bag->is_locked;
556 
557 		result = libfsapfs_container_key_bag_get_volume_key_bag_extent_by_identifier(
558 		          internal_volume->container_key_bag,
559 		          internal_volume->superblock->volume_identifier,
560 		          &key_bag_block_number,
561 		          &key_bag_number_of_blocks,
562 		          error );
563 
564 		if( result == -1 )
565 		{
566 			libcerror_error_set(
567 			 error,
568 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
569 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
570 			 "%s: unable to retrieve volume key bag extent.",
571 			 function );
572 
573 			goto on_error;
574 		}
575 		else if( result != 0 )
576 		{
577 			if( ( key_bag_block_number == 0 )
578 			 || ( key_bag_number_of_blocks == 0 ) )
579 			{
580 				libcerror_error_set(
581 				 error,
582 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
583 				 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
584 				 "%s: invalid volume key bag extent.",
585 				 function );
586 
587 				goto on_error;
588 			}
589 			if( libfsapfs_volume_key_bag_initialize(
590 			     &( internal_volume->key_bag ),
591 			     error ) != 1 )
592 			{
593 				libcerror_error_set(
594 				 error,
595 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
596 				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
597 				 "%s: unable to create volume key bag.",
598 				 function );
599 
600 				goto on_error;
601 			}
602 			file_offset = key_bag_block_number * internal_volume->io_handle->block_size;
603 
604 			if( libfsapfs_volume_key_bag_read_file_io_handle(
605 			     internal_volume->key_bag,
606 			     internal_volume->io_handle,
607 			     file_io_handle,
608 			     file_offset,
609 			     (size64_t) key_bag_number_of_blocks * internal_volume->io_handle->block_size,
610 			     internal_volume->superblock->volume_identifier,
611 			     error ) != 1 )
612 			{
613 				libcerror_error_set(
614 				 error,
615 				 LIBCERROR_ERROR_DOMAIN_IO,
616 				 LIBCERROR_IO_ERROR_READ_FAILED,
617 				 "%s: unable to read volume key bag at offset: %" PRIi64 " (0x%08" PRIx64 ").",
618 				 function,
619 				 file_offset,
620 				 file_offset );
621 
622 				goto on_error;
623 			}
624 			if( libfsapfs_encryption_context_initialize(
625 			     &( internal_volume->encryption_context ),
626 			     LIBFSAPFS_ENCRYPTION_METHOD_AES_128_XTS,
627 			     error ) != 1 )
628 			{
629 				libcerror_error_set(
630 				 error,
631 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
632 				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
633 				 "%s: unable to initialize encryption context.",
634 				 function );
635 
636 				goto on_error;
637 			}
638 			internal_volume->is_locked = 1;
639 		}
640 	}
641 #if defined( HAVE_DEBUG_OUTPUT )
642 	if( internal_volume->superblock->extent_reference_tree_block_number != 0 )
643 	{
644 		if( libfsapfs_extent_reference_tree_initialize(
645 		     &extent_reference_tree,
646 		     error ) != 1 )
647 		{
648 			libcerror_error_set(
649 			 error,
650 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
651 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
652 			 "%s: unable to create extent reference tree.",
653 			 function );
654 
655 			goto on_error;
656 		}
657 		file_offset = internal_volume->superblock->extent_reference_tree_block_number * internal_volume->io_handle->block_size;
658 
659 		if( libfsapfs_extent_reference_tree_read_file_io_handle(
660 		     extent_reference_tree,
661 		     file_io_handle,
662 		     file_offset,
663 		     error ) != 1 )
664 		{
665 			libcerror_error_set(
666 			 error,
667 			 LIBCERROR_ERROR_DOMAIN_IO,
668 			 LIBCERROR_IO_ERROR_READ_FAILED,
669 			 "%s: unable to read extent reference tree at offset: %" PRIi64 " (0x%08" PRIx64 ").",
670 			 function,
671 			 file_offset,
672 			 file_offset );
673 
674 			goto on_error;
675 		}
676 		if( libfsapfs_extent_reference_tree_free(
677 		     &extent_reference_tree,
678 		     error ) != 1 )
679 		{
680 			libcerror_error_set(
681 			 error,
682 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
683 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
684 			 "%s: unable to free extent reference tree.",
685 			 function );
686 
687 			goto on_error;
688 		}
689 	}
690 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
691 
692 	if( libcdata_array_initialize(
693 	     &( internal_volume->snapshots ),
694 	     0,
695 	     error ) != 1 )
696 	{
697 		libcerror_error_set(
698 		 error,
699 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
700 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
701 		 "%s: unable to create snapshots array.",
702 		 function );
703 
704 		goto on_error;
705 	}
706 	if( internal_volume->superblock->snapshot_metadata_tree_block_number != 0 )
707 	{
708 		if( libfsapfs_snapshot_metadata_tree_initialize(
709 		     &( internal_volume->snapshot_metadata_tree ),
710 		     internal_volume->io_handle,
711 		     internal_volume->container_data_block_vector,
712 		     internal_volume->object_map_btree,
713 		     internal_volume->superblock->snapshot_metadata_tree_block_number,
714 		     error ) != 1 )
715 		{
716 			libcerror_error_set(
717 			 error,
718 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
719 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
720 			 "%s: unable to create snapshot metadata tree.",
721 			 function );
722 
723 			goto on_error;
724 		}
725 		if( libfsapfs_snapshot_metadata_tree_get_snapshots(
726 		     internal_volume->snapshot_metadata_tree,
727 		     internal_volume->file_io_handle,
728 		     internal_volume->snapshots,
729 		     error ) == -1 )
730 		{
731 			libcerror_error_set(
732 			 error,
733 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
734 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
735 			 "%s: unable to retrieve snapshots.",
736 			 function );
737 
738 			goto on_error;
739 		}
740 	}
741 	if( internal_volume->superblock->file_system_root_object_identifier == 0 )
742 	{
743 		libcerror_error_set(
744 		 error,
745 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
746 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
747 		 "%s: invalid file system root object identifier - value out of bounds.",
748 		 function );
749 
750 		goto on_error;
751 	}
752 	if( libfsapfs_file_system_data_handle_initialize(
753 	     &file_system_data_handle,
754 	     internal_volume->io_handle,
755 	     internal_volume->encryption_context,
756 	     NULL,
757 	     error ) != 1 )
758 	{
759 		libcerror_error_set(
760 		 error,
761 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
762 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
763 		 "%s: unable to create file system data handle.",
764 		 function );
765 
766 		goto on_error;
767 	}
768 	if( libfdata_vector_initialize(
769 	     &( internal_volume->file_system_data_block_vector ),
770 	     (size64_t) internal_volume->io_handle->block_size,
771 	     (intptr_t *) file_system_data_handle,
772 	     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_file_system_data_handle_free,
773 	     NULL,
774 	     (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsapfs_file_system_data_handle_read_data_block,
775 	     NULL,
776 	     LIBFDATA_DATA_HANDLE_FLAG_MANAGED,
777 	     error ) != 1 )
778 	{
779 		libcerror_error_set(
780 		 error,
781 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
782 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
783 		 "%s: unable to create file system data block vector.",
784 		 function );
785 
786 		goto on_error;
787 	}
788 	internal_volume->file_system_data_handle = file_system_data_handle;
789 	file_system_data_handle                  = NULL;
790 
791 	if( libfdata_vector_append_segment(
792 	     internal_volume->file_system_data_block_vector,
793 	     &element_index,
794 	     0,
795 	     0,
796 	     internal_volume->io_handle->container_size,
797 	     0,
798 	     error ) != 1 )
799 	{
800 		libcerror_error_set(
801 		 error,
802 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
803 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
804 		 "%s: unable to append segment to file system data block vector.",
805 		 function );
806 
807 		goto on_error;
808 	}
809 	return( 1 );
810 
811 on_error:
812 	if( internal_volume->file_system_data_block_vector != NULL )
813 	{
814 		libfdata_vector_free(
815 		 &( internal_volume->file_system_data_block_vector ),
816 		 NULL );
817 	}
818 	if( file_system_data_handle != NULL )
819 	{
820 		libfsapfs_file_system_data_handle_free(
821 		 &file_system_data_handle,
822 		 NULL );
823 	}
824 	if( internal_volume->encryption_context != NULL )
825 	{
826 		libfsapfs_encryption_context_free(
827 		 &( internal_volume->encryption_context ),
828 		 NULL );
829 	}
830 	if( internal_volume->key_bag != NULL )
831 	{
832 		libfsapfs_volume_key_bag_free(
833 		 &( internal_volume->key_bag ),
834 		 NULL );
835 	}
836 	if( internal_volume->snapshot_metadata_tree != NULL )
837 	{
838 		libcdata_array_free(
839 		 &( internal_volume->snapshots ),
840 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
841 		 NULL );
842 	}
843 	if( internal_volume->snapshot_metadata_tree != NULL )
844 	{
845 		libfsapfs_snapshot_metadata_tree_free(
846 		 &( internal_volume->snapshot_metadata_tree ),
847 		 NULL );
848 	}
849 #if defined( HAVE_DEBUG_OUTPUT )
850 	if( extent_reference_tree != NULL )
851 	{
852 		libfsapfs_extent_reference_tree_free(
853 		 &extent_reference_tree,
854 		 NULL );
855 	}
856 #endif
857 	if( internal_volume->object_map_btree != NULL )
858 	{
859 		libfsapfs_object_map_btree_free(
860 		 &( internal_volume->object_map_btree ),
861 		 NULL );
862 	}
863 	if( object_map != NULL )
864 	{
865 		libfsapfs_object_map_free(
866 		 &object_map,
867 		 NULL );
868 	}
869 	if( internal_volume->container_data_block_vector != NULL )
870 	{
871 		libfdata_vector_free(
872 		 &( internal_volume->container_data_block_vector ),
873 		 NULL );
874 	}
875 	if( container_data_handle != NULL )
876 	{
877 		libfsapfs_container_data_handle_free(
878 		 &container_data_handle,
879 		 NULL );
880 	}
881 	if( internal_volume->superblock != NULL )
882 	{
883 		libfsapfs_volume_superblock_free(
884 		 &( internal_volume->superblock ),
885 		 NULL );
886 	}
887 	return( -1 );
888 }
889 
890 /* Closes a volume
891  * Returns 0 if successful or -1 on error
892  */
libfsapfs_internal_volume_close(libfsapfs_internal_volume_t * internal_volume,libcerror_error_t ** error)893 int libfsapfs_internal_volume_close(
894      libfsapfs_internal_volume_t *internal_volume,
895      libcerror_error_t **error )
896 {
897 	static char *function = "libfsapfs_internal_volume_close";
898 	int result            = 0;
899 
900 	if( internal_volume == NULL )
901 	{
902 		libcerror_error_set(
903 		 error,
904 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
905 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
906 		 "%s: invalid volume.",
907 		 function );
908 
909 		return( -1 );
910 	}
911 	if( internal_volume->io_handle == NULL )
912 	{
913 		libcerror_error_set(
914 		 error,
915 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
916 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
917 		 "%s: invalid volume - missing IO handle.",
918 		 function );
919 
920 		return( -1 );
921 	}
922 	internal_volume->file_io_handle = NULL;
923 	internal_volume->is_locked      = 1;
924 
925 	if( internal_volume->user_password != NULL )
926 	{
927 		if( memory_set(
928 		     internal_volume->user_password,
929 		     0,
930 		     internal_volume->user_password_size ) == NULL )
931 		{
932 			libcerror_error_set(
933 			 error,
934 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
935 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
936 			 "%s: unable to clear user password.",
937 			 function );
938 
939 			result = -1;
940 		}
941 		memory_free(
942 		 internal_volume->user_password );
943 
944 		internal_volume->user_password      = NULL;
945 		internal_volume->user_password_size = 0;
946 	}
947 	if( internal_volume->recovery_password != NULL )
948 	{
949 		if( memory_set(
950 		     internal_volume->recovery_password,
951 		     0,
952 		     internal_volume->recovery_password_size ) == NULL )
953 		{
954 			libcerror_error_set(
955 			 error,
956 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
957 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
958 			 "%s: unable to clear recovery password.",
959 			 function );
960 
961 			result = -1;
962 		}
963 		memory_free(
964 		 internal_volume->recovery_password );
965 
966 		internal_volume->recovery_password      = NULL;
967 		internal_volume->recovery_password_size = 0;
968 	}
969 	if( internal_volume->superblock != NULL )
970 	{
971 		if( libfsapfs_volume_superblock_free(
972 		     &( internal_volume->superblock ),
973 		     error ) != 1 )
974 		{
975 			libcerror_error_set(
976 			 error,
977 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
978 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
979 			 "%s: unable to free superblock.",
980 			 function );
981 
982 			result = -1;
983 		}
984 	}
985 	if( libfdata_vector_free(
986 	     &( internal_volume->container_data_block_vector ),
987 	     error ) != 1 )
988 	{
989 		libcerror_error_set(
990 		 error,
991 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
992 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
993 		 "%s: unable to free container data block vector.",
994 		 function );
995 
996 		result = -1;
997 	}
998 	if( internal_volume->object_map_btree != NULL )
999 	{
1000 		if( libfsapfs_object_map_btree_free(
1001 		     &( internal_volume->object_map_btree ),
1002 		     error ) != 1 )
1003 		{
1004 			libcerror_error_set(
1005 			 error,
1006 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1007 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1008 			 "%s: unable to free object map B-tree.",
1009 			 function );
1010 
1011 			result = -1;
1012 		}
1013 	}
1014 	if( internal_volume->snapshot_metadata_tree != NULL )
1015 	{
1016 		if( libfsapfs_snapshot_metadata_tree_free(
1017 		     &( internal_volume->snapshot_metadata_tree ),
1018 		     error ) != 1 )
1019 		{
1020 			libcerror_error_set(
1021 			 error,
1022 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1023 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1024 			 "%s: unable to free snapshot metadata tree.",
1025 			 function );
1026 
1027 			result = -1;
1028 		}
1029 	}
1030 	if( internal_volume->snapshots != NULL )
1031 	{
1032 		if( libcdata_array_free(
1033 		     &( internal_volume->snapshots ),
1034 		     (int (*)(intptr_t **, libcerror_error_t **)) &libfsapfs_snapshot_metadata_free,
1035 		     error ) != 1 )
1036 		{
1037 			libcerror_error_set(
1038 			 error,
1039 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1040 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1041 			 "%s: unable to free snapshots array.",
1042 			 function );
1043 
1044 			result = -1;
1045 		}
1046 	}
1047 	if( internal_volume->key_bag != NULL )
1048 	{
1049 		if( libfsapfs_volume_key_bag_free(
1050 		     &( internal_volume->key_bag ),
1051 		     error ) != 1 )
1052 		{
1053 			libcerror_error_set(
1054 			 error,
1055 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1056 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1057 			 "%s: unable to free key bag.",
1058 			 function );
1059 
1060 			result = -1;
1061 		}
1062 	}
1063 	if( internal_volume->encryption_context != NULL )
1064 	{
1065 		if( libfsapfs_encryption_context_free(
1066 		     &( internal_volume->encryption_context ),
1067 		     error ) != 1 )
1068 		{
1069 			libcerror_error_set(
1070 			 error,
1071 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1072 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1073 			 "%s: unable to free encryption context.",
1074 			 function );
1075 
1076 			result = -1;
1077 		}
1078 	}
1079 	if( libfdata_vector_free(
1080 	     &( internal_volume->file_system_data_block_vector ),
1081 	     error ) != 1 )
1082 	{
1083 		libcerror_error_set(
1084 		 error,
1085 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1086 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1087 		 "%s: unable to free file system data block vector.",
1088 		 function );
1089 
1090 		result = -1;
1091 	}
1092 	if( internal_volume->file_system_btree != NULL )
1093 	{
1094 		if( libfsapfs_file_system_btree_free(
1095 		     &( internal_volume->file_system_btree ),
1096 		     error ) != 1 )
1097 		{
1098 			libcerror_error_set(
1099 			 error,
1100 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1101 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1102 			 "%s: unable to free file system B-tree.",
1103 			 function );
1104 
1105 			result = -1;
1106 		}
1107 	}
1108 	return( result );
1109 }
1110 
1111 /* Unlocks an encrypted volume
1112  * Returns 1 if the volume is unlocked, 0 if not or -1 on error
1113  */
libfsapfs_internal_volume_unlock(libfsapfs_internal_volume_t * internal_volume,libcerror_error_t ** error)1114 int libfsapfs_internal_volume_unlock(
1115      libfsapfs_internal_volume_t *internal_volume,
1116      libcerror_error_t **error )
1117 {
1118 	uint8_t volume_key[ 32 ];
1119 	uint8_t volume_master_key[ 32 ];
1120 
1121 	static char *function = "libfsapfs_internal_volume_unlock";
1122 	int result            = 0;
1123 
1124 	if( internal_volume == NULL )
1125 	{
1126 		libcerror_error_set(
1127 		 error,
1128 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1129 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1130 		 "%s: invalid volume.",
1131 		 function );
1132 
1133 		return( -1 );
1134 	}
1135 	if( internal_volume->superblock == NULL )
1136 	{
1137 		libcerror_error_set(
1138 		 error,
1139 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1140 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1141 		 "%s: invalid volume - missing superblock.",
1142 		 function );
1143 
1144 		return( -1 );
1145 	}
1146 	if( internal_volume->key_bag == NULL )
1147 	{
1148 		libcerror_error_set(
1149 		 error,
1150 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1152 		 "%s: invalid volume - missing key bag.",
1153 		 function );
1154 
1155 		return( -1 );
1156 	}
1157 	result = libfsapfs_volume_key_bag_get_volume_key(
1158 	          internal_volume->key_bag,
1159 	          internal_volume->user_password,
1160 	          internal_volume->user_password_size - 1,
1161 	          internal_volume->recovery_password,
1162 	          internal_volume->recovery_password_size - 1,
1163 	          volume_key,
1164 	          256,
1165 	          error );
1166 
1167 	if( result == -1 )
1168 	{
1169 		libcerror_error_set(
1170 		 error,
1171 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1172 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1173 		 "%s: unable to retrieve volume key using password.",
1174 		 function );
1175 
1176 		goto on_error;
1177 	}
1178 	else if( result != 0 )
1179 	{
1180 		if( libfsapfs_container_key_bag_get_volume_master_key_by_identifier(
1181 		     internal_volume->container_key_bag,
1182 		     internal_volume->superblock->volume_identifier,
1183 		     volume_key,
1184 		     256,
1185 		     volume_master_key,
1186 		     256,
1187 		     error ) != 1 )
1188 		{
1189 			libcerror_error_set(
1190 			 error,
1191 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1192 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1193 			 "%s: unable to retrieve volume master key.",
1194 			 function );
1195 
1196 			goto on_error;
1197 		}
1198 		memory_set(
1199 		 volume_key,
1200 		 0,
1201 		 32 );
1202 
1203 		if( libfsapfs_encryption_context_set_keys(
1204 		     internal_volume->encryption_context,
1205 		     volume_master_key,
1206 		     16,
1207 		     &( volume_master_key[ 16 ] ),
1208 		     16,
1209 		     error ) != 1 )
1210 		{
1211 			libcerror_error_set(
1212 			 error,
1213 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1214 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1215 			 "%s: unable to set keys in encryption context.",
1216 			 function );
1217 
1218 			goto on_error;
1219 		}
1220 		memory_set(
1221 		 volume_master_key,
1222 		 0,
1223 		 32 );
1224 	}
1225 	if( result != 0 )
1226 	{
1227 		internal_volume->is_locked = 0;
1228 	}
1229 	return( result );
1230 
1231 on_error:
1232 	memory_set(
1233 	 volume_master_key,
1234 	 0,
1235 	 32 );
1236 
1237 	memory_set(
1238 	 volume_key,
1239 	 0,
1240 	 32 );
1241 
1242 	return( -1 );
1243 }
1244 
1245 /* Unlocks the volume
1246  * Returns 1 if the volume is unlocked, 0 if not or -1 on error
1247  */
libfsapfs_volume_unlock(libfsapfs_volume_t * volume,libcerror_error_t ** error)1248 int libfsapfs_volume_unlock(
1249      libfsapfs_volume_t *volume,
1250      libcerror_error_t **error )
1251 {
1252 	libfsapfs_internal_volume_t *internal_volume = NULL;
1253 	static char *function                        = "libfsapfs_volume_unlock";
1254 	int result                                   = 1;
1255 
1256 	if( volume == NULL )
1257 	{
1258 		libcerror_error_set(
1259 		 error,
1260 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1261 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1262 		 "%s: invalid volume.",
1263 		 function );
1264 
1265 		return( -1 );
1266 	}
1267 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1268 
1269 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1270 	if( libcthreads_read_write_lock_grab_for_write(
1271 	     internal_volume->read_write_lock,
1272 	     error ) != 1 )
1273 	{
1274 		libcerror_error_set(
1275 		 error,
1276 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1277 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1278 		 "%s: unable to grab read/write lock for writing.",
1279 		 function );
1280 
1281 		return( -1 );
1282 	}
1283 #endif
1284 	if( internal_volume->is_locked != 0 )
1285 	{
1286 		result = libfsapfs_internal_volume_unlock(
1287 		          internal_volume,
1288 		          error );
1289 
1290 		if( result == -1 )
1291 		{
1292 			libcerror_error_set(
1293 			 error,
1294 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1295 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
1296 			 "%s: unable to unlock volume.",
1297 			 function );
1298 
1299 			result = -1;
1300 		}
1301 	}
1302 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1303 	if( libcthreads_read_write_lock_release_for_write(
1304 	     internal_volume->read_write_lock,
1305 	     error ) != 1 )
1306 	{
1307 		libcerror_error_set(
1308 		 error,
1309 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1310 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1311 		 "%s: unable to release read/write lock for writing.",
1312 		 function );
1313 
1314 		return( -1 );
1315 	}
1316 #endif
1317 	return( result );
1318 }
1319 
1320 /* Retrieves the feature flags
1321  * Returns 1 if successful or -1 on error
1322  */
libfsapfs_volume_get_features_flags(libfsapfs_volume_t * volume,uint64_t * compatible_features_flags,uint64_t * incompatible_features_flags,uint64_t * read_only_compatible_features_flags,libcerror_error_t ** error)1323 int libfsapfs_volume_get_features_flags(
1324      libfsapfs_volume_t *volume,
1325      uint64_t *compatible_features_flags,
1326      uint64_t *incompatible_features_flags,
1327      uint64_t *read_only_compatible_features_flags,
1328      libcerror_error_t **error )
1329 {
1330 	libfsapfs_internal_volume_t *internal_volume = NULL;
1331 	static char *function                        = "libfsapfs_volume_get_features_flags";
1332 
1333 	if( volume == NULL )
1334 	{
1335 		libcerror_error_set(
1336 		 error,
1337 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1338 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1339 		 "%s: invalid volume.",
1340 		 function );
1341 
1342 		return( -1 );
1343 	}
1344 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1345 
1346 	if( internal_volume->superblock == NULL )
1347 	{
1348 		libcerror_error_set(
1349 		 error,
1350 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1351 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1352 		 "%s: invalid volume - missing superblock.",
1353 		 function );
1354 
1355 		return( -1 );
1356 	}
1357 	if( compatible_features_flags == NULL )
1358 	{
1359 		libcerror_error_set(
1360 		 error,
1361 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1362 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1363 		 "%s: invalid compatible features flags.",
1364 		 function );
1365 
1366 		return( -1 );
1367 	}
1368 	if( incompatible_features_flags == NULL )
1369 	{
1370 		libcerror_error_set(
1371 		 error,
1372 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1373 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1374 		 "%s: invalid incompatible features flags.",
1375 		 function );
1376 
1377 		return( -1 );
1378 	}
1379 	if( read_only_compatible_features_flags == NULL )
1380 	{
1381 		libcerror_error_set(
1382 		 error,
1383 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1384 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1385 		 "%s: invalid read-only compatible features flags.",
1386 		 function );
1387 
1388 		return( -1 );
1389 	}
1390 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1391 	if( libcthreads_read_write_lock_grab_for_read(
1392 	     internal_volume->read_write_lock,
1393 	     error ) != 1 )
1394 	{
1395 		libcerror_error_set(
1396 		 error,
1397 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1398 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1399 		 "%s: unable to grab read/write lock for reading.",
1400 		 function );
1401 
1402 		return( -1 );
1403 	}
1404 #endif
1405 	*compatible_features_flags           = internal_volume->superblock->compatible_features_flags;
1406 	*incompatible_features_flags         = internal_volume->superblock->incompatible_features_flags;
1407 	*read_only_compatible_features_flags = internal_volume->superblock->read_only_compatible_features_flags;
1408 
1409 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1410 	if( libcthreads_read_write_lock_release_for_read(
1411 	     internal_volume->read_write_lock,
1412 	     error ) != 1 )
1413 	{
1414 		libcerror_error_set(
1415 		 error,
1416 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1417 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1418 		 "%s: unable to release read/write lock for reading.",
1419 		 function );
1420 
1421 		return( -1 );
1422 	}
1423 #endif
1424 	return( 1 );
1425 }
1426 
1427 /* Retrieves the size
1428  * Returns 1 if successful or -1 on error
1429  */
libfsapfs_volume_get_size(libfsapfs_volume_t * volume,size64_t * size,libcerror_error_t ** error)1430 int libfsapfs_volume_get_size(
1431      libfsapfs_volume_t *volume,
1432      size64_t *size,
1433      libcerror_error_t **error )
1434 {
1435 	libfsapfs_internal_volume_t *internal_volume = NULL;
1436 	static char *function                        = "libfsapfs_volume_get_size";
1437 
1438 	if( volume == NULL )
1439 	{
1440 		libcerror_error_set(
1441 		 error,
1442 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1443 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1444 		 "%s: invalid volume.",
1445 		 function );
1446 
1447 		return( -1 );
1448 	}
1449 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1450 
1451 	if( internal_volume->superblock == NULL )
1452 	{
1453 		libcerror_error_set(
1454 		 error,
1455 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1456 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1457 		 "%s: invalid volume - missing superblock.",
1458 		 function );
1459 
1460 		return( -1 );
1461 	}
1462 	if( size == NULL )
1463 	{
1464 		libcerror_error_set(
1465 		 error,
1466 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1467 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1468 		 "%s: invalid size.",
1469 		 function );
1470 
1471 		return( -1 );
1472 	}
1473 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1474 	if( libcthreads_read_write_lock_grab_for_read(
1475 	     internal_volume->read_write_lock,
1476 	     error ) != 1 )
1477 	{
1478 		libcerror_error_set(
1479 		 error,
1480 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1481 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1482 		 "%s: unable to grab read/write lock for reading.",
1483 		 function );
1484 
1485 		return( -1 );
1486 	}
1487 #endif
1488 /* TODO implement */
1489 	*size = (size64_t) 0;
1490 
1491 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1492 	if( libcthreads_read_write_lock_release_for_read(
1493 	     internal_volume->read_write_lock,
1494 	     error ) != 1 )
1495 	{
1496 		libcerror_error_set(
1497 		 error,
1498 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1499 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1500 		 "%s: unable to release read/write lock for reading.",
1501 		 function );
1502 
1503 		return( -1 );
1504 	}
1505 #endif
1506 	return( -1 );
1507 }
1508 
1509 /* Retrieves the identifier
1510  * The identifier is an UUID stored in big-endian and is 16 bytes of size
1511  * Returns 1 if successful or -1 on error
1512  */
libfsapfs_volume_get_identifier(libfsapfs_volume_t * volume,uint8_t * uuid_data,size_t uuid_data_size,libcerror_error_t ** error)1513 int libfsapfs_volume_get_identifier(
1514      libfsapfs_volume_t *volume,
1515      uint8_t *uuid_data,
1516      size_t uuid_data_size,
1517      libcerror_error_t **error )
1518 {
1519 	libfsapfs_internal_volume_t *internal_volume = NULL;
1520 	static char *function                        = "libfsapfs_volume_get_identifier";
1521 	int result                                   = 1;
1522 
1523 	if( volume == NULL )
1524 	{
1525 		libcerror_error_set(
1526 		 error,
1527 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1528 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1529 		 "%s: invalid volume.",
1530 		 function );
1531 
1532 		return( -1 );
1533 	}
1534 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1535 
1536 	if( internal_volume->superblock == NULL )
1537 	{
1538 		libcerror_error_set(
1539 		 error,
1540 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1541 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1542 		 "%s: invalid volume - missing superblock.",
1543 		 function );
1544 
1545 		return( -1 );
1546 	}
1547 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1548 	if( libcthreads_read_write_lock_grab_for_read(
1549 	     internal_volume->read_write_lock,
1550 	     error ) != 1 )
1551 	{
1552 		libcerror_error_set(
1553 		 error,
1554 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1555 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1556 		 "%s: unable to grab read/write lock for reading.",
1557 		 function );
1558 
1559 		return( -1 );
1560 	}
1561 #endif
1562 	if( libfsapfs_volume_superblock_get_volume_identifier(
1563 	     internal_volume->superblock,
1564 	     uuid_data,
1565 	     uuid_data_size,
1566 	     error ) != 1 )
1567 	{
1568 		libcerror_error_set(
1569 		 error,
1570 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1571 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1572 		 "%s: unable to retrieve volume identifier.",
1573 		 function );
1574 
1575 		result = -1;
1576 	}
1577 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1578 	if( libcthreads_read_write_lock_release_for_read(
1579 	     internal_volume->read_write_lock,
1580 	     error ) != 1 )
1581 	{
1582 		libcerror_error_set(
1583 		 error,
1584 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1585 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1586 		 "%s: unable to release read/write lock for reading.",
1587 		 function );
1588 
1589 		return( -1 );
1590 	}
1591 #endif
1592 	return( result );
1593 }
1594 
1595 /* Retrieves the size of the UTF-8 encoded name
1596  * The returned size includes the end of string character
1597  * Returns 1 if successful or -1 on error
1598  */
libfsapfs_volume_get_utf8_name_size(libfsapfs_volume_t * volume,size_t * utf8_string_size,libcerror_error_t ** error)1599 int libfsapfs_volume_get_utf8_name_size(
1600      libfsapfs_volume_t *volume,
1601      size_t *utf8_string_size,
1602      libcerror_error_t **error )
1603 {
1604 	libfsapfs_internal_volume_t *internal_volume = NULL;
1605 	static char *function                        = "libfsapfs_volume_get_utf8_name_size";
1606 	int result                                   = 1;
1607 
1608 	if( volume == NULL )
1609 	{
1610 		libcerror_error_set(
1611 		 error,
1612 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1613 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1614 		 "%s: invalid volume.",
1615 		 function );
1616 
1617 		return( -1 );
1618 	}
1619 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1620 
1621 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1622 	if( libcthreads_read_write_lock_grab_for_read(
1623 	     internal_volume->read_write_lock,
1624 	     error ) != 1 )
1625 	{
1626 		libcerror_error_set(
1627 		 error,
1628 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1629 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1630 		 "%s: unable to grab read/write lock for reading.",
1631 		 function );
1632 
1633 		return( -1 );
1634 	}
1635 #endif
1636 	if( libfsapfs_volume_superblock_get_utf8_volume_name_size(
1637 	     internal_volume->superblock,
1638 	     utf8_string_size,
1639 	     error ) != 1 )
1640 	{
1641 		libcerror_error_set(
1642 		 error,
1643 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1644 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1645 		 "%s: unable to retrieve UTF-8 string size.",
1646 		 function );
1647 
1648 		result = -1;
1649 	}
1650 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1651 	if( libcthreads_read_write_lock_release_for_read(
1652 	     internal_volume->read_write_lock,
1653 	     error ) != 1 )
1654 	{
1655 		libcerror_error_set(
1656 		 error,
1657 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1658 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1659 		 "%s: unable to release read/write lock for reading.",
1660 		 function );
1661 
1662 		return( -1 );
1663 	}
1664 #endif
1665 	return( result );
1666 }
1667 
1668 /* Retrieves the UTF-8 encoded name
1669  * The size should include the end of string character
1670  * Returns 1 if successful or -1 on error
1671  */
libfsapfs_volume_get_utf8_name(libfsapfs_volume_t * volume,uint8_t * utf8_string,size_t utf8_string_size,libcerror_error_t ** error)1672 int libfsapfs_volume_get_utf8_name(
1673      libfsapfs_volume_t *volume,
1674      uint8_t *utf8_string,
1675      size_t utf8_string_size,
1676      libcerror_error_t **error )
1677 {
1678 	libfsapfs_internal_volume_t *internal_volume = NULL;
1679 	static char *function                        = "libfsapfs_volume_get_utf8_name";
1680 	int result                                   = 1;
1681 
1682 	if( volume == NULL )
1683 	{
1684 		libcerror_error_set(
1685 		 error,
1686 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1687 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1688 		 "%s: invalid volume.",
1689 		 function );
1690 
1691 		return( -1 );
1692 	}
1693 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1694 
1695 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1696 	if( libcthreads_read_write_lock_grab_for_read(
1697 	     internal_volume->read_write_lock,
1698 	     error ) != 1 )
1699 	{
1700 		libcerror_error_set(
1701 		 error,
1702 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1703 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1704 		 "%s: unable to grab read/write lock for reading.",
1705 		 function );
1706 
1707 		return( -1 );
1708 	}
1709 #endif
1710 	if( libfsapfs_volume_superblock_get_utf8_volume_name(
1711 	     internal_volume->superblock,
1712 	     utf8_string,
1713 	     utf8_string_size,
1714 	     error ) != 1 )
1715 	{
1716 		libcerror_error_set(
1717 		 error,
1718 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1719 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1720 		 "%s: unable to retrieve UTF-8 string.",
1721 		 function );
1722 
1723 		result = -1;
1724 	}
1725 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1726 	if( libcthreads_read_write_lock_release_for_read(
1727 	     internal_volume->read_write_lock,
1728 	     error ) != 1 )
1729 	{
1730 		libcerror_error_set(
1731 		 error,
1732 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1733 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1734 		 "%s: unable to release read/write lock for reading.",
1735 		 function );
1736 
1737 		return( -1 );
1738 	}
1739 #endif
1740 	return( result );
1741 }
1742 
1743 /* Retrieves the size of the UTF-16 encoded name
1744  * The returned size includes the end of string character
1745  * Returns 1 if successful or -1 on error
1746  */
libfsapfs_volume_get_utf16_name_size(libfsapfs_volume_t * volume,size_t * utf16_string_size,libcerror_error_t ** error)1747 int libfsapfs_volume_get_utf16_name_size(
1748      libfsapfs_volume_t *volume,
1749      size_t *utf16_string_size,
1750      libcerror_error_t **error )
1751 {
1752 	libfsapfs_internal_volume_t *internal_volume = NULL;
1753 	static char *function                        = "libfsapfs_volume_get_utf16_name_size";
1754 	int result                                   = 1;
1755 
1756 	if( volume == NULL )
1757 	{
1758 		libcerror_error_set(
1759 		 error,
1760 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1761 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1762 		 "%s: invalid volume.",
1763 		 function );
1764 
1765 		return( -1 );
1766 	}
1767 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1768 
1769 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1770 	if( libcthreads_read_write_lock_grab_for_read(
1771 	     internal_volume->read_write_lock,
1772 	     error ) != 1 )
1773 	{
1774 		libcerror_error_set(
1775 		 error,
1776 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1777 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1778 		 "%s: unable to grab read/write lock for reading.",
1779 		 function );
1780 
1781 		return( -1 );
1782 	}
1783 #endif
1784 	if( libfsapfs_volume_superblock_get_utf16_volume_name_size(
1785 	     internal_volume->superblock,
1786 	     utf16_string_size,
1787 	     error ) != 1 )
1788 	{
1789 		libcerror_error_set(
1790 		 error,
1791 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1792 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1793 		 "%s: unable to retrieve UTF-16 string size.",
1794 		 function );
1795 
1796 		result = -1;
1797 	}
1798 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1799 	if( libcthreads_read_write_lock_release_for_read(
1800 	     internal_volume->read_write_lock,
1801 	     error ) != 1 )
1802 	{
1803 		libcerror_error_set(
1804 		 error,
1805 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1806 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1807 		 "%s: unable to release read/write lock for reading.",
1808 		 function );
1809 
1810 		return( -1 );
1811 	}
1812 #endif
1813 	return( result );
1814 }
1815 
1816 /* Retrieves the UTF-16 encoded name
1817  * The size should include the end of string character
1818  * Returns 1 if successful or -1 on error
1819  */
libfsapfs_volume_get_utf16_name(libfsapfs_volume_t * volume,uint16_t * utf16_string,size_t utf16_string_size,libcerror_error_t ** error)1820 int libfsapfs_volume_get_utf16_name(
1821      libfsapfs_volume_t *volume,
1822      uint16_t *utf16_string,
1823      size_t utf16_string_size,
1824      libcerror_error_t **error )
1825 {
1826 	libfsapfs_internal_volume_t *internal_volume = NULL;
1827 	static char *function                        = "libfsapfs_volume_get_utf16_name";
1828 	int result                                   = 1;
1829 
1830 	if( volume == NULL )
1831 	{
1832 		libcerror_error_set(
1833 		 error,
1834 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1835 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1836 		 "%s: invalid volume.",
1837 		 function );
1838 
1839 		return( -1 );
1840 	}
1841 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1842 
1843 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1844 	if( libcthreads_read_write_lock_grab_for_read(
1845 	     internal_volume->read_write_lock,
1846 	     error ) != 1 )
1847 	{
1848 		libcerror_error_set(
1849 		 error,
1850 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1851 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1852 		 "%s: unable to grab read/write lock for reading.",
1853 		 function );
1854 
1855 		return( -1 );
1856 	}
1857 #endif
1858 	if( libfsapfs_volume_superblock_get_utf16_volume_name(
1859 	     internal_volume->superblock,
1860 	     utf16_string,
1861 	     utf16_string_size,
1862 	     error ) != 1 )
1863 	{
1864 		libcerror_error_set(
1865 		 error,
1866 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1867 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1868 		 "%s: unable to retrieve UTF-16 string.",
1869 		 function );
1870 
1871 		result = -1;
1872 	}
1873 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1874 	if( libcthreads_read_write_lock_release_for_read(
1875 	     internal_volume->read_write_lock,
1876 	     error ) != 1 )
1877 	{
1878 		libcerror_error_set(
1879 		 error,
1880 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1881 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1882 		 "%s: unable to release read/write lock for reading.",
1883 		 function );
1884 
1885 		return( -1 );
1886 	}
1887 #endif
1888 	return( result );
1889 }
1890 
1891 /* Determines if the volume is locked
1892  * Returns 1 if locked, 0 if not or -1 on error
1893  */
libfsapfs_volume_is_locked(libfsapfs_volume_t * volume,libcerror_error_t ** error)1894 int libfsapfs_volume_is_locked(
1895      libfsapfs_volume_t *volume,
1896      libcerror_error_t **error )
1897 {
1898 	libfsapfs_internal_volume_t *internal_volume = NULL;
1899 	static char *function                        = "libfsapfs_volume_is_locked";
1900 	uint8_t is_locked                            = 0;
1901 
1902 	if( volume == NULL )
1903 	{
1904 		libcerror_error_set(
1905 		 error,
1906 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1907 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1908 		 "%s: invalid volume.",
1909 		 function );
1910 
1911 		return( -1 );
1912 	}
1913 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1914 
1915 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1916 	if( libcthreads_read_write_lock_grab_for_read(
1917 	     internal_volume->read_write_lock,
1918 	     error ) != 1 )
1919 	{
1920 		libcerror_error_set(
1921 		 error,
1922 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1923 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1924 		 "%s: unable to grab read/write lock for reading.",
1925 		 function );
1926 
1927 		return( -1 );
1928 	}
1929 #endif
1930 	is_locked = internal_volume->is_locked;
1931 
1932 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1933 	if( libcthreads_read_write_lock_release_for_read(
1934 	     internal_volume->read_write_lock,
1935 	     error ) != 1 )
1936 	{
1937 		libcerror_error_set(
1938 		 error,
1939 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1940 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1941 		 "%s: unable to release read/write lock for reading.",
1942 		 function );
1943 
1944 		return( -1 );
1945 	}
1946 #endif
1947 	return( is_locked );
1948 }
1949 
1950 /* Sets an UTF-8 formatted password
1951  * This function needs to be used before one of the open or unlock functions
1952  * Returns 1 if successful, 0 if password is invalid or -1 on error
1953  */
libfsapfs_volume_set_utf8_password(libfsapfs_volume_t * volume,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)1954 int libfsapfs_volume_set_utf8_password(
1955      libfsapfs_volume_t *volume,
1956      const uint8_t *utf8_string,
1957      size_t utf8_string_length,
1958      libcerror_error_t **error )
1959 {
1960 	libfsapfs_internal_volume_t *internal_volume = NULL;
1961 	static char *function                        = "libfsapfs_volume_set_utf8_password";
1962 
1963 	if( volume == NULL )
1964 	{
1965 		libcerror_error_set(
1966 		 error,
1967 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1968 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1969 		 "%s: invalid volume.",
1970 		 function );
1971 
1972 		return( -1 );
1973 	}
1974 	internal_volume = (libfsapfs_internal_volume_t *) volume;
1975 
1976 	if( utf8_string == NULL )
1977 	{
1978 		libcerror_error_set(
1979 		 error,
1980 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1981 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1982 		 "%s: invalid UTF-8 string.",
1983 		 function );
1984 
1985 		return( -1 );
1986 	}
1987 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
1988 	if( libcthreads_read_write_lock_grab_for_write(
1989 	     internal_volume->read_write_lock,
1990 	     error ) != 1 )
1991 	{
1992 		libcerror_error_set(
1993 		 error,
1994 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1995 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1996 		 "%s: unable to grab read/write lock for writing.",
1997 		 function );
1998 
1999 		return( -1 );
2000 	}
2001 #endif
2002 	if( internal_volume->user_password != NULL )
2003 	{
2004 		if( memory_set(
2005 		     internal_volume->user_password,
2006 		     0,
2007 		     internal_volume->user_password_size ) == NULL )
2008 		{
2009 			libcerror_error_set(
2010 			 error,
2011 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2012 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2013 			 "%s: unable to clear user password.",
2014 			 function );
2015 
2016 			goto on_error;
2017 		}
2018 		memory_free(
2019 		 internal_volume->user_password );
2020 
2021 		internal_volume->user_password      = NULL;
2022 		internal_volume->user_password_size = 0;
2023 	}
2024 	internal_volume->user_password_size = narrow_string_length(
2025 	                                       (char *) utf8_string );
2026 
2027 	if( ( internal_volume->user_password_size == 0 )
2028 	 || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2029 	{
2030 		libcerror_error_set(
2031 		 error,
2032 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2033 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2034 		 "%s: invalid volume - user password size value out of bounds.",
2035 		 function );
2036 
2037 		goto on_error;
2038 	}
2039 	internal_volume->user_password_size += 1;
2040 
2041 	internal_volume->user_password = (uint8_t *) memory_allocate(
2042 	                                              sizeof( uint8_t ) * internal_volume->user_password_size );
2043 
2044 	if( internal_volume->user_password == NULL )
2045 	{
2046 		libcerror_error_set(
2047 		 error,
2048 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2049 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2050 		 "%s: unable to create user password.",
2051 		 function );
2052 
2053 		goto on_error;
2054 	}
2055 	if( memory_copy(
2056 	     internal_volume->user_password,
2057 	     utf8_string,
2058 	     utf8_string_length ) == NULL )
2059 	{
2060 		libcerror_error_set(
2061 		 error,
2062 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2063 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2064 		 "%s: unable to copy user password.",
2065 		 function );
2066 
2067 		goto on_error;
2068 	}
2069 	internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2070 
2071 	internal_volume->user_password_is_set = 1;
2072 
2073 #if defined( HAVE_DEBUG_OUTPUT )
2074 	if( libcnotify_verbose != 0 )
2075 	{
2076 		libcnotify_printf(
2077 		 "%s: user password: %s\n",
2078 		 function,
2079 		 internal_volume->user_password );
2080 	}
2081 #endif
2082 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2083 	if( libcthreads_read_write_lock_release_for_write(
2084 	     internal_volume->read_write_lock,
2085 	     error ) != 1 )
2086 	{
2087 		libcerror_error_set(
2088 		 error,
2089 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2090 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2091 		 "%s: unable to release read/write lock for writing.",
2092 		 function );
2093 
2094 		return( -1 );
2095 	}
2096 #endif
2097 	return( 1 );
2098 
2099 on_error:
2100 	if( internal_volume->user_password != NULL )
2101 	{
2102 		memory_set(
2103 		 internal_volume->user_password,
2104 		 0,
2105 		 internal_volume->user_password_size );
2106 		memory_free(
2107 		 internal_volume->user_password );
2108 
2109 		internal_volume->user_password = NULL;
2110 	}
2111 	internal_volume->user_password_size = 0;
2112 
2113 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2114 	libcthreads_read_write_lock_release_for_write(
2115 	 internal_volume->read_write_lock,
2116 	 NULL );
2117 #endif
2118 	return( -1 );
2119 }
2120 
2121 /* Sets an UTF-16 formatted password
2122  * This function needs to be used before one of the open or unlock functions
2123  * Returns 1 if successful, 0 if password is invalid or -1 on error
2124  */
libfsapfs_volume_set_utf16_password(libfsapfs_volume_t * volume,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)2125 int libfsapfs_volume_set_utf16_password(
2126      libfsapfs_volume_t *volume,
2127      const uint16_t *utf16_string,
2128      size_t utf16_string_length,
2129      libcerror_error_t **error )
2130 {
2131 	libfsapfs_internal_volume_t *internal_volume = NULL;
2132 	static char *function                        = "libfsapfs_volume_set_utf16_password";
2133 
2134 	if( volume == NULL )
2135 	{
2136 		libcerror_error_set(
2137 		 error,
2138 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2139 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2140 		 "%s: invalid volume.",
2141 		 function );
2142 
2143 		return( -1 );
2144 	}
2145 	internal_volume = (libfsapfs_internal_volume_t *) volume;
2146 
2147 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2148 	if( libcthreads_read_write_lock_grab_for_write(
2149 	     internal_volume->read_write_lock,
2150 	     error ) != 1 )
2151 	{
2152 		libcerror_error_set(
2153 		 error,
2154 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2155 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2156 		 "%s: unable to grab read/write lock for writing.",
2157 		 function );
2158 
2159 		return( -1 );
2160 	}
2161 #endif
2162 	if( internal_volume->user_password != NULL )
2163 	{
2164 		if( memory_set(
2165 		     internal_volume->user_password,
2166 		     0,
2167 		     internal_volume->user_password_size ) == NULL )
2168 		{
2169 			libcerror_error_set(
2170 			 error,
2171 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2172 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2173 			 "%s: unable to clear user password.",
2174 			 function );
2175 
2176 			goto on_error;
2177 		}
2178 		memory_free(
2179 		 internal_volume->user_password );
2180 
2181 		internal_volume->user_password      = NULL;
2182 		internal_volume->user_password_size = 0;
2183 	}
2184 	if( libuna_utf8_string_size_from_utf16(
2185 	     utf16_string,
2186 	     utf16_string_length,
2187 	     &( internal_volume->user_password_size ),
2188 	     error ) != 1 )
2189 	{
2190 		libcerror_error_set(
2191 		 error,
2192 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2193 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2194 		 "%s: unable to set password size.",
2195 		 function );
2196 
2197 		goto on_error;
2198 	}
2199 	if( ( internal_volume->user_password_size == 0 )
2200 	 || ( internal_volume->user_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2201 	{
2202 		libcerror_error_set(
2203 		 error,
2204 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2205 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2206 		 "%s: invalid volume - user password size value out of bounds.",
2207 		 function );
2208 
2209 		goto on_error;
2210 	}
2211 	internal_volume->user_password_size += 1;
2212 
2213 	internal_volume->user_password = (uint8_t *) memory_allocate(
2214 	                                              sizeof( uint8_t ) * internal_volume->user_password_size );
2215 
2216 	if( internal_volume->user_password == NULL )
2217 	{
2218 		libcerror_error_set(
2219 		 error,
2220 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2221 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2222 		 "%s: unable to create user password.",
2223 		 function );
2224 
2225 		goto on_error;
2226 	}
2227 	if( libuna_utf8_string_copy_from_utf16(
2228 	     internal_volume->user_password,
2229 	     internal_volume->user_password_size,
2230 	     utf16_string,
2231 	     utf16_string_length,
2232 	     error ) != 1 )
2233 	{
2234 		libcerror_error_set(
2235 		 error,
2236 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2237 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2238 		 "%s: unable to copy user password.",
2239 		 function );
2240 
2241 		goto on_error;
2242 	}
2243 	internal_volume->user_password[ internal_volume->user_password_size - 1 ] = 0;
2244 
2245 	internal_volume->user_password_is_set = 1;
2246 
2247 #if defined( HAVE_DEBUG_OUTPUT )
2248 	if( libcnotify_verbose != 0 )
2249 	{
2250 		libcnotify_printf(
2251 		 "%s: user password: %s\n",
2252 		 function,
2253 		 internal_volume->user_password );
2254 	}
2255 #endif
2256 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2257 	if( libcthreads_read_write_lock_release_for_write(
2258 	     internal_volume->read_write_lock,
2259 	     error ) != 1 )
2260 	{
2261 		libcerror_error_set(
2262 		 error,
2263 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2264 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2265 		 "%s: unable to release read/write lock for writing.",
2266 		 function );
2267 
2268 		return( -1 );
2269 	}
2270 #endif
2271 	return( 1 );
2272 
2273 on_error:
2274 	if( internal_volume->user_password != NULL )
2275 	{
2276 		memory_set(
2277 		 internal_volume->user_password,
2278 		 0,
2279 		 internal_volume->user_password_size );
2280 		memory_free(
2281 		 internal_volume->user_password );
2282 
2283 		internal_volume->user_password = NULL;
2284 	}
2285 	internal_volume->user_password_size = 0;
2286 
2287 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2288 	libcthreads_read_write_lock_release_for_write(
2289 	 internal_volume->read_write_lock,
2290 	 NULL );
2291 #endif
2292 	return( -1 );
2293 }
2294 
2295 /* Sets an UTF-8 formatted recovery password
2296  * This function needs to be used before one of the open or unlock functions
2297  * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2298  */
libfsapfs_volume_set_utf8_recovery_password(libfsapfs_volume_t * volume,const uint8_t * utf8_string,size_t utf8_string_length,libcerror_error_t ** error)2299 int libfsapfs_volume_set_utf8_recovery_password(
2300      libfsapfs_volume_t *volume,
2301      const uint8_t *utf8_string,
2302      size_t utf8_string_length,
2303      libcerror_error_t **error )
2304 {
2305 	libfsapfs_internal_volume_t *internal_volume = NULL;
2306 	static char *function                        = "libfsapfs_volume_set_utf8_recovery_password";
2307 
2308 	if( volume == NULL )
2309 	{
2310 		libcerror_error_set(
2311 		 error,
2312 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2313 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2314 		 "%s: invalid volume.",
2315 		 function );
2316 
2317 		return( -1 );
2318 	}
2319 	internal_volume = (libfsapfs_internal_volume_t *) volume;
2320 
2321 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2322 	if( libcthreads_read_write_lock_grab_for_write(
2323 	     internal_volume->read_write_lock,
2324 	     error ) != 1 )
2325 	{
2326 		libcerror_error_set(
2327 		 error,
2328 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2329 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2330 		 "%s: unable to grab read/write lock for writing.",
2331 		 function );
2332 
2333 		return( -1 );
2334 	}
2335 #endif
2336 	if( internal_volume->recovery_password != NULL )
2337 	{
2338 		if( memory_set(
2339 		     internal_volume->recovery_password,
2340 		     0,
2341 		     internal_volume->recovery_password_size ) == NULL )
2342 		{
2343 			libcerror_error_set(
2344 			 error,
2345 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2346 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2347 			 "%s: unable to clear recovery password.",
2348 			 function );
2349 
2350 			goto on_error;
2351 		}
2352 		memory_free(
2353 		 internal_volume->recovery_password );
2354 
2355 		internal_volume->recovery_password      = NULL;
2356 		internal_volume->recovery_password_size = 0;
2357 	}
2358 	internal_volume->recovery_password_size = narrow_string_length(
2359 	                                           (char *) utf8_string );
2360 
2361 	if( ( internal_volume->recovery_password_size == 0 )
2362 	 || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2363 	{
2364 		libcerror_error_set(
2365 		 error,
2366 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2367 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2368 		 "%s: invalid volume - user recovery password size value out of bounds.",
2369 		 function );
2370 
2371 		goto on_error;
2372 	}
2373 	internal_volume->recovery_password_size += 1;
2374 
2375 	internal_volume->recovery_password = (uint8_t *) memory_allocate(
2376 	                                                  sizeof( uint8_t ) * internal_volume->recovery_password_size );
2377 
2378 	if( internal_volume->recovery_password == NULL )
2379 	{
2380 		libcerror_error_set(
2381 		 error,
2382 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2383 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2384 		 "%s: unable to create recovery password.",
2385 		 function );
2386 
2387 		goto on_error;
2388 	}
2389 	if( memory_copy(
2390 	     internal_volume->recovery_password,
2391 	     utf8_string,
2392 	     utf8_string_length ) == NULL )
2393 	{
2394 		libcerror_error_set(
2395 		 error,
2396 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
2397 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
2398 		 "%s: unable to copy recovery password.",
2399 		 function );
2400 
2401 		goto on_error;
2402 	}
2403 	internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2404 
2405 	internal_volume->recovery_password_is_set = 1;
2406 
2407 #if defined( HAVE_DEBUG_OUTPUT )
2408 	if( libcnotify_verbose != 0 )
2409 	{
2410 		libcnotify_printf(
2411 		 "%s: recovery password: %s\n",
2412 		 function,
2413 		 internal_volume->recovery_password );
2414 	}
2415 #endif
2416 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2417 	if( libcthreads_read_write_lock_release_for_write(
2418 	     internal_volume->read_write_lock,
2419 	     error ) != 1 )
2420 	{
2421 		libcerror_error_set(
2422 		 error,
2423 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2424 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2425 		 "%s: unable to release read/write lock for writing.",
2426 		 function );
2427 
2428 		return( -1 );
2429 	}
2430 #endif
2431 	return( 1 );
2432 
2433 on_error:
2434 	if( internal_volume->recovery_password != NULL )
2435 	{
2436 		memory_set(
2437 		 internal_volume->recovery_password,
2438 		 0,
2439 		 internal_volume->recovery_password_size );
2440 		memory_free(
2441 		 internal_volume->recovery_password );
2442 
2443 		internal_volume->recovery_password = NULL;
2444 	}
2445 	internal_volume->recovery_password_size = 0;
2446 
2447 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2448 	libcthreads_read_write_lock_release_for_write(
2449 	 internal_volume->read_write_lock,
2450 	 NULL );
2451 #endif
2452 	return( -1 );
2453 }
2454 
2455 /* Sets an UTF-16 formatted recovery password
2456  * This function needs to be used before one of the open or unlock functions
2457  * Returns 1 if successful, 0 if recovery password is invalid or -1 on error
2458  */
libfsapfs_volume_set_utf16_recovery_password(libfsapfs_volume_t * volume,const uint16_t * utf16_string,size_t utf16_string_length,libcerror_error_t ** error)2459 int libfsapfs_volume_set_utf16_recovery_password(
2460      libfsapfs_volume_t *volume,
2461      const uint16_t *utf16_string,
2462      size_t utf16_string_length,
2463      libcerror_error_t **error )
2464 {
2465 	libfsapfs_internal_volume_t *internal_volume = NULL;
2466 	static char *function                        = "libfsapfs_volume_set_utf16_recovery_password";
2467 
2468 	if( volume == NULL )
2469 	{
2470 		libcerror_error_set(
2471 		 error,
2472 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2473 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2474 		 "%s: invalid volume.",
2475 		 function );
2476 
2477 		return( -1 );
2478 	}
2479 	internal_volume = (libfsapfs_internal_volume_t *) volume;
2480 
2481 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2482 	if( libcthreads_read_write_lock_grab_for_write(
2483 	     internal_volume->read_write_lock,
2484 	     error ) != 1 )
2485 	{
2486 		libcerror_error_set(
2487 		 error,
2488 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2489 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2490 		 "%s: unable to grab read/write lock for writing.",
2491 		 function );
2492 
2493 		return( -1 );
2494 	}
2495 #endif
2496 	if( internal_volume->recovery_password != NULL )
2497 	{
2498 		if( memory_set(
2499 		     internal_volume->recovery_password,
2500 		     0,
2501 		     internal_volume->recovery_password_size ) == NULL )
2502 		{
2503 			libcerror_error_set(
2504 			 error,
2505 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
2506 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
2507 			 "%s: unable to clear recovery password.",
2508 			 function );
2509 
2510 			goto on_error;
2511 		}
2512 		memory_free(
2513 		 internal_volume->recovery_password );
2514 
2515 		internal_volume->recovery_password      = NULL;
2516 		internal_volume->recovery_password_size = 0;
2517 	}
2518 	if( libuna_utf8_string_size_from_utf16(
2519 	     utf16_string,
2520 	     utf16_string_length,
2521 	     &( internal_volume->recovery_password_size ),
2522 	     error ) != 1 )
2523 	{
2524 		libcerror_error_set(
2525 		 error,
2526 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2527 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2528 		 "%s: unable to set password size.",
2529 		 function );
2530 
2531 		goto on_error;
2532 	}
2533 	if( ( internal_volume->recovery_password_size == 0 )
2534 	 || ( internal_volume->recovery_password_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 1 ) ) )
2535 	{
2536 		libcerror_error_set(
2537 		 error,
2538 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2539 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
2540 		 "%s: invalid volume - user recovery password size value out of bounds.",
2541 		 function );
2542 
2543 		goto on_error;
2544 	}
2545 	internal_volume->recovery_password_size += 1;
2546 
2547 	internal_volume->recovery_password = (uint8_t *) memory_allocate(
2548 	                                                  sizeof( uint8_t ) * internal_volume->recovery_password_size );
2549 
2550 	if( internal_volume->recovery_password == NULL )
2551 	{
2552 		libcerror_error_set(
2553 		 error,
2554 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2555 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2556 		 "%s: unable to create recovery password.",
2557 		 function );
2558 
2559 		goto on_error;
2560 	}
2561 	if( libuna_utf8_string_copy_from_utf16(
2562 	     internal_volume->recovery_password,
2563 	     internal_volume->recovery_password_size,
2564 	     utf16_string,
2565 	     utf16_string_length,
2566 	     error ) != 1 )
2567 	{
2568 		libcerror_error_set(
2569 		 error,
2570 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2571 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2572 		 "%s: unable to copy recovery password.",
2573 		 function );
2574 
2575 		goto on_error;
2576 	}
2577 	internal_volume->recovery_password[ internal_volume->recovery_password_size - 1 ] = 0;
2578 
2579 	internal_volume->recovery_password_is_set = 1;
2580 
2581 #if defined( HAVE_DEBUG_OUTPUT )
2582 	if( libcnotify_verbose != 0 )
2583 	{
2584 		libcnotify_printf(
2585 		 "%s: recovery password: %s\n",
2586 		 function,
2587 		 internal_volume->recovery_password );
2588 	}
2589 #endif
2590 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2591 	if( libcthreads_read_write_lock_release_for_write(
2592 	     internal_volume->read_write_lock,
2593 	     error ) != 1 )
2594 	{
2595 		libcerror_error_set(
2596 		 error,
2597 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2598 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2599 		 "%s: unable to release read/write lock for writing.",
2600 		 function );
2601 
2602 		return( -1 );
2603 	}
2604 #endif
2605 	return( 1 );
2606 
2607 on_error:
2608 	if( internal_volume->recovery_password != NULL )
2609 	{
2610 		memory_set(
2611 		 internal_volume->recovery_password,
2612 		 0,
2613 		 internal_volume->recovery_password_size );
2614 		memory_free(
2615 		 internal_volume->recovery_password );
2616 
2617 		internal_volume->recovery_password = NULL;
2618 	}
2619 	internal_volume->recovery_password_size = 0;
2620 
2621 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2622 	libcthreads_read_write_lock_release_for_write(
2623 	 internal_volume->read_write_lock,
2624 	 NULL );
2625 #endif
2626 	return( -1 );
2627 }
2628 
2629 /* Retrieves the next file entry identifier
2630  * Returns 1 if successful or -1 on error
2631  */
libfsapfs_volume_get_next_file_entry_identifier(libfsapfs_volume_t * volume,uint64_t * identifier,libcerror_error_t ** error)2632 int libfsapfs_volume_get_next_file_entry_identifier(
2633      libfsapfs_volume_t *volume,
2634      uint64_t *identifier,
2635      libcerror_error_t **error )
2636 {
2637 	libfsapfs_internal_volume_t *internal_volume = NULL;
2638 	static char *function                        = "libfsapfs_volume_get_next_file_entry_identifier";
2639 
2640 	if( volume == NULL )
2641 	{
2642 		libcerror_error_set(
2643 		 error,
2644 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2645 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2646 		 "%s: invalid volume.",
2647 		 function );
2648 
2649 		return( -1 );
2650 	}
2651 	internal_volume = (libfsapfs_internal_volume_t *) volume;
2652 
2653 	if( identifier == NULL )
2654 	{
2655 		libcerror_error_set(
2656 		 error,
2657 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2658 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2659 		 "%s: invalid identifier.",
2660 		 function );
2661 
2662 		return( -1 );
2663 	}
2664 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2665 	if( libcthreads_read_write_lock_grab_for_read(
2666 	     internal_volume->read_write_lock,
2667 	     error ) != 1 )
2668 	{
2669 		libcerror_error_set(
2670 		 error,
2671 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2672 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2673 		 "%s: unable to grab read/write lock for reading.",
2674 		 function );
2675 
2676 		return( -1 );
2677 	}
2678 #endif
2679 	*identifier = internal_volume->superblock->next_file_system_object_identifier;
2680 
2681 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2682 	if( libcthreads_read_write_lock_release_for_read(
2683 	     internal_volume->read_write_lock,
2684 	     error ) != 1 )
2685 	{
2686 		libcerror_error_set(
2687 		 error,
2688 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2689 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2690 		 "%s: unable to release read/write lock for reading.",
2691 		 function );
2692 
2693 		return( -1 );
2694 	}
2695 #endif
2696 	return( 1 );
2697 }
2698 
2699 /* Determines the file system B-tree
2700  * Returns 1 if successful or -1 on error
2701  */
libfsapfs_internal_volume_get_file_system_btree(libfsapfs_internal_volume_t * internal_volume,libcerror_error_t ** error)2702 int libfsapfs_internal_volume_get_file_system_btree(
2703      libfsapfs_internal_volume_t *internal_volume,
2704      libcerror_error_t **error )
2705 {
2706 	libfsapfs_object_map_descriptor_t *object_map_descriptor = NULL;
2707 	static char *function                                    = "libfsapfs_internal_volume_get_file_system_btree";
2708 	uint8_t use_case_folding                                 = 0;
2709 
2710 	if( internal_volume == NULL )
2711 	{
2712 		libcerror_error_set(
2713 		 error,
2714 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2715 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2716 		 "%s: invalid volume.",
2717 		 function );
2718 
2719 		return( -1 );
2720 	}
2721 	if( internal_volume->superblock == NULL )
2722 	{
2723 		libcerror_error_set(
2724 		 error,
2725 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2726 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2727 		 "%s: invalid volume - missing superblock.",
2728 		 function );
2729 
2730 		return( -1 );
2731 	}
2732 	if( internal_volume->is_locked != 0 )
2733 	{
2734 		if( libfsapfs_internal_volume_unlock(
2735 		     internal_volume,
2736 		     error ) != 1 )
2737 		{
2738 			libcerror_error_set(
2739 			 error,
2740 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2741 			 LIBCERROR_RUNTIME_ERROR_GENERIC,
2742 			 "%s: unable to unlock volume.",
2743 			 function );
2744 
2745 			goto on_error;
2746 		}
2747 	}
2748 	if( libfsapfs_object_map_btree_get_descriptor_by_object_identifier(
2749 	     internal_volume->object_map_btree,
2750 	     internal_volume->file_io_handle,
2751 	     internal_volume->superblock->file_system_root_object_identifier,
2752 	     &object_map_descriptor,
2753 	     error ) != 1 )
2754 	{
2755 		libcerror_error_set(
2756 		 error,
2757 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2758 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2759 		 "%s: unable to retrieve object map descriptor for file system root object identifier: %" PRIu64 ".",
2760 		 function,
2761 		 internal_volume->superblock->file_system_root_object_identifier );
2762 
2763 		goto on_error;
2764 	}
2765 	if( object_map_descriptor == NULL )
2766 	{
2767 		libcerror_error_set(
2768 		 error,
2769 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2770 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
2771 		 "%s: invalid object map descriptor.",
2772 		 function );
2773 
2774 		goto on_error;
2775 	}
2776 	if( ( internal_volume->superblock->incompatible_features_flags & 0x00000000000000001 ) != 0 )
2777 	{
2778 		use_case_folding = 1;
2779 	}
2780 	if( libfsapfs_file_system_btree_initialize(
2781 	     &( internal_volume->file_system_btree ),
2782 	     internal_volume->io_handle,
2783 	     internal_volume->encryption_context,
2784 	     internal_volume->file_system_data_block_vector,
2785 	     internal_volume->object_map_btree,
2786 	     object_map_descriptor->physical_address,
2787 	     use_case_folding,
2788 	     error ) != 1 )
2789 	{
2790 		libcerror_error_set(
2791 		 error,
2792 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2793 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2794 		 "%s: unable to create file system B-tree.",
2795 		 function );
2796 
2797 		goto on_error;
2798 	}
2799 	if( libfsapfs_object_map_descriptor_free(
2800 	     &object_map_descriptor,
2801 	     error ) != 1 )
2802 	{
2803 		libcerror_error_set(
2804 		 error,
2805 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2806 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2807 		 "%s: unable to free object map descriptor.",
2808 		 function );
2809 
2810 		goto on_error;
2811 	}
2812 	return( 1 );
2813 
2814 on_error:
2815 	if( object_map_descriptor != NULL )
2816 	{
2817 		libfsapfs_object_map_descriptor_free(
2818 		 &object_map_descriptor,
2819 		 NULL );
2820 	}
2821 	if( internal_volume->file_system_btree != NULL )
2822 	{
2823 		libfsapfs_file_system_btree_free(
2824 		 &( internal_volume->file_system_btree ),
2825 		 NULL );
2826 	}
2827 	return( -1 );
2828 }
2829 
2830 /* Retrieves the file entry for a specific identifier
2831  * Returns 1 if successful, 0 if not available or -1 on error
2832  */
libfsapfs_volume_get_file_entry_by_identifier(libfsapfs_volume_t * volume,uint64_t identifier,libfsapfs_file_entry_t ** file_entry,libcerror_error_t ** error)2833 int libfsapfs_volume_get_file_entry_by_identifier(
2834      libfsapfs_volume_t *volume,
2835      uint64_t identifier,
2836      libfsapfs_file_entry_t **file_entry,
2837      libcerror_error_t **error )
2838 {
2839 	libfsapfs_inode_t *inode                     = NULL;
2840 	libfsapfs_internal_volume_t *internal_volume = NULL;
2841 	static char *function                        = "libfsapfs_volume_get_file_entry_by_identifier";
2842 	int result                                   = 0;
2843 
2844 	if( volume == NULL )
2845 	{
2846 		libcerror_error_set(
2847 		 error,
2848 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2849 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2850 		 "%s: invalid volume.",
2851 		 function );
2852 
2853 		return( -1 );
2854 	}
2855 	internal_volume = (libfsapfs_internal_volume_t *) volume;
2856 
2857 	if( file_entry == NULL )
2858 	{
2859 		libcerror_error_set(
2860 		 error,
2861 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2862 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2863 		 "%s: invalid file entry.",
2864 		 function );
2865 
2866 		return( -1 );
2867 	}
2868 	if( *file_entry != NULL )
2869 	{
2870 		libcerror_error_set(
2871 		 error,
2872 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2873 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2874 		 "%s: invalid file entry value already set.",
2875 		 function );
2876 
2877 		return( -1 );
2878 	}
2879 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2880 	if( libcthreads_read_write_lock_grab_for_write(
2881 	     internal_volume->read_write_lock,
2882 	     error ) != 1 )
2883 	{
2884 		libcerror_error_set(
2885 		 error,
2886 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2887 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2888 		 "%s: unable to grab read/write lock for writing.",
2889 		 function );
2890 
2891 		return( -1 );
2892 	}
2893 #endif
2894 	if( internal_volume->file_system_btree == NULL )
2895 	{
2896 		if( libfsapfs_internal_volume_get_file_system_btree(
2897 		     internal_volume,
2898 		     error ) != 1 )
2899 		{
2900 			libcerror_error_set(
2901 			 error,
2902 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2903 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2904 			 "%s: unable to determine file system B-tree.",
2905 			 function );
2906 
2907 			goto on_error;
2908 		}
2909 	}
2910 	result = libfsapfs_file_system_btree_get_inode_by_identifier(
2911 	          internal_volume->file_system_btree,
2912 	          internal_volume->file_io_handle,
2913 	          identifier,
2914 	          &inode,
2915 	          error );
2916 
2917 	if( result == -1 )
2918 	{
2919 		libcerror_error_set(
2920 		 error,
2921 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2922 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2923 		 "%s: unable to retrieve inode: %" PRIu64 " from file system B-tree.",
2924 		 function,
2925 		 identifier );
2926 
2927 		goto on_error;
2928 	}
2929 	else if( result != 0 )
2930 	{
2931 		if( libfsapfs_file_entry_initialize(
2932 		     file_entry,
2933 		     internal_volume->io_handle,
2934 		     internal_volume->file_io_handle,
2935 		     internal_volume->encryption_context,
2936 		     internal_volume->file_system_btree,
2937 		     inode,
2938 		     NULL,
2939 		     error ) != 1 )
2940 		{
2941 			libcerror_error_set(
2942 			 error,
2943 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2944 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2945 			 "%s: unable to create file entry.",
2946 			 function );
2947 
2948 			goto on_error;
2949 		}
2950 	}
2951 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2952 	if( libcthreads_read_write_lock_release_for_write(
2953 	     internal_volume->read_write_lock,
2954 	     error ) != 1 )
2955 	{
2956 		libcerror_error_set(
2957 		 error,
2958 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
2959 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2960 		 "%s: unable to release read/write lock for writing.",
2961 		 function );
2962 
2963 		return( -1 );
2964 	}
2965 #endif
2966 	return( result );
2967 
2968 on_error:
2969 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
2970 	libcthreads_read_write_lock_release_for_write(
2971 	 internal_volume->read_write_lock,
2972 	 NULL );
2973 #endif
2974 	return( -1 );
2975 }
2976 
2977 /* Retrieves the root directory file entry
2978  * Returns 1 if successful or -1 on error
2979  */
libfsapfs_volume_get_root_directory(libfsapfs_volume_t * volume,libfsapfs_file_entry_t ** file_entry,libcerror_error_t ** error)2980 int libfsapfs_volume_get_root_directory(
2981      libfsapfs_volume_t *volume,
2982      libfsapfs_file_entry_t **file_entry,
2983      libcerror_error_t **error )
2984 {
2985 	libfsapfs_inode_t *inode                     = NULL;
2986 	libfsapfs_internal_volume_t *internal_volume = NULL;
2987 	static char *function                        = "libfsapfs_volume_get_root_directory";
2988 	int result                                   = 0;
2989 
2990 	if( volume == NULL )
2991 	{
2992 		libcerror_error_set(
2993 		 error,
2994 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2995 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2996 		 "%s: invalid volume.",
2997 		 function );
2998 
2999 		return( -1 );
3000 	}
3001 	internal_volume = (libfsapfs_internal_volume_t *) volume;
3002 
3003 	if( file_entry == NULL )
3004 	{
3005 		libcerror_error_set(
3006 		 error,
3007 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3008 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3009 		 "%s: invalid file entry.",
3010 		 function );
3011 
3012 		return( -1 );
3013 	}
3014 	if( *file_entry != NULL )
3015 	{
3016 		libcerror_error_set(
3017 		 error,
3018 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3019 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3020 		 "%s: invalid file entry value already set.",
3021 		 function );
3022 
3023 		return( -1 );
3024 	}
3025 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3026 	if( libcthreads_read_write_lock_grab_for_write(
3027 	     internal_volume->read_write_lock,
3028 	     error ) != 1 )
3029 	{
3030 		libcerror_error_set(
3031 		 error,
3032 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3033 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3034 		 "%s: unable to grab read/write lock for writing.",
3035 		 function );
3036 
3037 		return( -1 );
3038 	}
3039 #endif
3040 	if( internal_volume->file_system_btree == NULL )
3041 	{
3042 		if( libfsapfs_internal_volume_get_file_system_btree(
3043 		     internal_volume,
3044 		     error ) != 1 )
3045 		{
3046 			libcerror_error_set(
3047 			 error,
3048 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3049 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3050 			 "%s: unable to determine file system B-tree.",
3051 			 function );
3052 
3053 			goto on_error;
3054 		}
3055 	}
3056 	result = libfsapfs_file_system_btree_get_inode_by_identifier(
3057 	          internal_volume->file_system_btree,
3058 	          internal_volume->file_io_handle,
3059 	          2,
3060 	          &inode,
3061 	          error );
3062 
3063 	if( result != 1 )
3064 	{
3065 		libcerror_error_set(
3066 		 error,
3067 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3068 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3069 		 "%s: unable to retrieve root directory inode from file system B-tree.",
3070 		 function );
3071 
3072 		goto on_error;
3073 	}
3074 /* TODO return 0 if no root directory inode */
3075 
3076 	if( libfsapfs_file_entry_initialize(
3077 	     file_entry,
3078 	     internal_volume->io_handle,
3079 	     internal_volume->file_io_handle,
3080 	     internal_volume->encryption_context,
3081 	     internal_volume->file_system_btree,
3082 	     inode,
3083 	     NULL,
3084 	     error ) != 1 )
3085 	{
3086 		libcerror_error_set(
3087 		 error,
3088 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3089 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3090 		 "%s: unable to create file entry.",
3091 		 function );
3092 
3093 		goto on_error;
3094 	}
3095 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3096 	if( libcthreads_read_write_lock_release_for_write(
3097 	     internal_volume->read_write_lock,
3098 	     error ) != 1 )
3099 	{
3100 		libcerror_error_set(
3101 		 error,
3102 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3103 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3104 		 "%s: unable to release read/write lock for writing.",
3105 		 function );
3106 
3107 		return( -1 );
3108 	}
3109 #endif
3110 	return( 1 );
3111 
3112 on_error:
3113 	if( inode != NULL )
3114 	{
3115 		libfsapfs_inode_free(
3116 		 &inode,
3117 		 NULL );
3118 	}
3119 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3120 	libcthreads_read_write_lock_release_for_write(
3121 	 internal_volume->read_write_lock,
3122 	 NULL );
3123 #endif
3124 	return( -1 );
3125 }
3126 
3127 /* Retrieves the file entry for an UTF-8 encoded path
3128  * Returns 1 if successful, 0 if no such file entry or -1 on error
3129  */
libfsapfs_volume_get_file_entry_by_utf8_path(libfsapfs_volume_t * volume,const uint8_t * utf8_string,size_t utf8_string_length,libfsapfs_file_entry_t ** file_entry,libcerror_error_t ** error)3130 int libfsapfs_volume_get_file_entry_by_utf8_path(
3131      libfsapfs_volume_t *volume,
3132      const uint8_t *utf8_string,
3133      size_t utf8_string_length,
3134      libfsapfs_file_entry_t **file_entry,
3135      libcerror_error_t **error )
3136 {
3137 	libfsapfs_directory_record_t *directory_record = NULL;
3138 	libfsapfs_inode_t *inode                       = NULL;
3139 	libfsapfs_internal_volume_t *internal_volume   = NULL;
3140 	static char *function                          = "libfsapfs_volume_get_file_entry_by_utf8_path";
3141 	int result                                     = 0;
3142 
3143 	if( volume == NULL )
3144 	{
3145 		libcerror_error_set(
3146 		 error,
3147 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3148 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3149 		 "%s: invalid volume.",
3150 		 function );
3151 
3152 		return( -1 );
3153 	}
3154 	internal_volume = (libfsapfs_internal_volume_t *) volume;
3155 
3156 	if( file_entry == NULL )
3157 	{
3158 		libcerror_error_set(
3159 		 error,
3160 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3161 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3162 		 "%s: invalid file entry.",
3163 		 function );
3164 
3165 		return( -1 );
3166 	}
3167 	if( *file_entry != NULL )
3168 	{
3169 		libcerror_error_set(
3170 		 error,
3171 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3172 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3173 		 "%s: invalid file entry value already set.",
3174 		 function );
3175 
3176 		return( -1 );
3177 	}
3178 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3179 	if( libcthreads_read_write_lock_grab_for_write(
3180 	     internal_volume->read_write_lock,
3181 	     error ) != 1 )
3182 	{
3183 		libcerror_error_set(
3184 		 error,
3185 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3186 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3187 		 "%s: unable to grab read/write lock for writing.",
3188 		 function );
3189 
3190 		return( -1 );
3191 	}
3192 #endif
3193 	if( internal_volume->file_system_btree == NULL )
3194 	{
3195 		if( libfsapfs_internal_volume_get_file_system_btree(
3196 		     internal_volume,
3197 		     error ) != 1 )
3198 		{
3199 			libcerror_error_set(
3200 			 error,
3201 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3202 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3203 			 "%s: unable to determine file system B-tree.",
3204 			 function );
3205 
3206 			goto on_error;
3207 		}
3208 	}
3209 	result = libfsapfs_file_system_btree_get_inode_by_utf8_path(
3210 	          internal_volume->file_system_btree,
3211 	          internal_volume->file_io_handle,
3212 	          2,
3213 	          utf8_string,
3214 	          utf8_string_length,
3215 	          &inode,
3216 	          &directory_record,
3217 	          error );
3218 
3219 	if( result == -1 )
3220 	{
3221 		libcerror_error_set(
3222 		 error,
3223 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3224 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3225 		 "%s: unable to retrieve inode from file system B-tree.",
3226 		 function );
3227 
3228 		goto on_error;
3229 	}
3230 	else if( result != 0 )
3231 	{
3232 		if( libfsapfs_file_entry_initialize(
3233 		     file_entry,
3234 		     internal_volume->io_handle,
3235 		     internal_volume->file_io_handle,
3236 		     internal_volume->encryption_context,
3237 		     internal_volume->file_system_btree,
3238 		     inode,
3239 		     directory_record,
3240 		     error ) != 1 )
3241 		{
3242 			libcerror_error_set(
3243 			 error,
3244 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3245 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3246 			 "%s: unable to create file entry.",
3247 			 function );
3248 
3249 			goto on_error;
3250 		}
3251 		inode            = NULL;
3252 		directory_record = NULL;
3253 	}
3254 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3255 	if( libcthreads_read_write_lock_release_for_write(
3256 	     internal_volume->read_write_lock,
3257 	     error ) != 1 )
3258 	{
3259 		libcerror_error_set(
3260 		 error,
3261 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3262 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3263 		 "%s: unable to release read/write lock for writing.",
3264 		 function );
3265 
3266 		return( -1 );
3267 	}
3268 #endif
3269 	return( result );
3270 
3271 on_error:
3272 	if( *file_entry != NULL )
3273 	{
3274 		libfsapfs_file_entry_free(
3275 		 file_entry,
3276 		 NULL );
3277 	}
3278 	if( directory_record != NULL )
3279 	{
3280 		libfsapfs_directory_record_free(
3281 		 &directory_record,
3282 		 NULL );
3283 	}
3284 	if( inode != NULL )
3285 	{
3286 		libfsapfs_inode_free(
3287 		 &inode,
3288 		 NULL );
3289 	}
3290 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3291 	libcthreads_read_write_lock_release_for_write(
3292 	 internal_volume->read_write_lock,
3293 	 NULL );
3294 #endif
3295 	return( -1 );
3296 }
3297 
3298 /* Retrieves the file entry for an UTF-16 encoded path
3299  * Returns 1 if successful, 0 if no such file entry or -1 on error
3300  */
libfsapfs_volume_get_file_entry_by_utf16_path(libfsapfs_volume_t * volume,const uint16_t * utf16_string,size_t utf16_string_length,libfsapfs_file_entry_t ** file_entry,libcerror_error_t ** error)3301 int libfsapfs_volume_get_file_entry_by_utf16_path(
3302      libfsapfs_volume_t *volume,
3303      const uint16_t *utf16_string,
3304      size_t utf16_string_length,
3305      libfsapfs_file_entry_t **file_entry,
3306      libcerror_error_t **error )
3307 {
3308 	libfsapfs_directory_record_t *directory_record = NULL;
3309 	libfsapfs_inode_t *inode                       = NULL;
3310 	libfsapfs_internal_volume_t *internal_volume   = NULL;
3311 	static char *function                          = "libfsapfs_volume_get_file_entry_by_utf16_path";
3312 	int result                                     = 0;
3313 
3314 	if( volume == NULL )
3315 	{
3316 		libcerror_error_set(
3317 		 error,
3318 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3319 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3320 		 "%s: invalid volume.",
3321 		 function );
3322 
3323 		return( -1 );
3324 	}
3325 	internal_volume = (libfsapfs_internal_volume_t *) volume;
3326 
3327 	if( file_entry == NULL )
3328 	{
3329 		libcerror_error_set(
3330 		 error,
3331 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3332 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3333 		 "%s: invalid file entry.",
3334 		 function );
3335 
3336 		return( -1 );
3337 	}
3338 	if( *file_entry != NULL )
3339 	{
3340 		libcerror_error_set(
3341 		 error,
3342 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3343 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3344 		 "%s: invalid file entry value already set.",
3345 		 function );
3346 
3347 		return( -1 );
3348 	}
3349 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3350 	if( libcthreads_read_write_lock_grab_for_write(
3351 	     internal_volume->read_write_lock,
3352 	     error ) != 1 )
3353 	{
3354 		libcerror_error_set(
3355 		 error,
3356 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3357 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3358 		 "%s: unable to grab read/write lock for writing.",
3359 		 function );
3360 
3361 		return( -1 );
3362 	}
3363 #endif
3364 	if( internal_volume->file_system_btree == NULL )
3365 	{
3366 		if( libfsapfs_internal_volume_get_file_system_btree(
3367 		     internal_volume,
3368 		     error ) != 1 )
3369 		{
3370 			libcerror_error_set(
3371 			 error,
3372 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3373 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3374 			 "%s: unable to determine file system B-tree.",
3375 			 function );
3376 
3377 			goto on_error;
3378 		}
3379 	}
3380 	result = libfsapfs_file_system_btree_get_inode_by_utf16_path(
3381 	          internal_volume->file_system_btree,
3382 	          internal_volume->file_io_handle,
3383 	          2,
3384 	          utf16_string,
3385 	          utf16_string_length,
3386 	          &inode,
3387 	          &directory_record,
3388 	          error );
3389 
3390 	if( result == -1 )
3391 	{
3392 		libcerror_error_set(
3393 		 error,
3394 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3395 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3396 		 "%s: unable to retrieve inode from file system B-tree.",
3397 		 function );
3398 
3399 		goto on_error;
3400 	}
3401 	else if( result != 0 )
3402 	{
3403 		if( libfsapfs_file_entry_initialize(
3404 		     file_entry,
3405 		     internal_volume->io_handle,
3406 		     internal_volume->file_io_handle,
3407 		     internal_volume->encryption_context,
3408 		     internal_volume->file_system_btree,
3409 		     inode,
3410 		     directory_record,
3411 		     error ) != 1 )
3412 		{
3413 			libcerror_error_set(
3414 			 error,
3415 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3416 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3417 			 "%s: unable to create file entry.",
3418 			 function );
3419 
3420 			goto on_error;
3421 		}
3422 		inode            = NULL;
3423 		directory_record = NULL;
3424 	}
3425 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3426 	if( libcthreads_read_write_lock_release_for_write(
3427 	     internal_volume->read_write_lock,
3428 	     error ) != 1 )
3429 	{
3430 		libcerror_error_set(
3431 		 error,
3432 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3433 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3434 		 "%s: unable to release read/write lock for writing.",
3435 		 function );
3436 
3437 		return( -1 );
3438 	}
3439 #endif
3440 	return( result );
3441 
3442 on_error:
3443 	if( *file_entry != NULL )
3444 	{
3445 		libfsapfs_file_entry_free(
3446 		 file_entry,
3447 		 NULL );
3448 	}
3449 	if( directory_record != NULL )
3450 	{
3451 		libfsapfs_directory_record_free(
3452 		 &directory_record,
3453 		 NULL );
3454 	}
3455 	if( inode != NULL )
3456 	{
3457 		libfsapfs_inode_free(
3458 		 &inode,
3459 		 NULL );
3460 	}
3461 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3462 	libcthreads_read_write_lock_release_for_write(
3463 	 internal_volume->read_write_lock,
3464 	 NULL );
3465 #endif
3466 	return( -1 );
3467 }
3468 
3469 /* Retrieves the number of snapshots
3470  * Returns 1 if successful or -1 on error
3471  */
libfsapfs_volume_get_number_of_snapshots(libfsapfs_volume_t * volume,int * number_of_snapshots,libcerror_error_t ** error)3472 int libfsapfs_volume_get_number_of_snapshots(
3473      libfsapfs_volume_t *volume,
3474      int *number_of_snapshots,
3475      libcerror_error_t **error )
3476 {
3477 	libfsapfs_internal_volume_t *internal_volume = NULL;
3478 	static char *function                        = "libfsapfs_volume_get_number_of_snapshots";
3479 	int result                                   = 1;
3480 
3481 	if( volume == NULL )
3482 	{
3483 		libcerror_error_set(
3484 		 error,
3485 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3486 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3487 		 "%s: invalid volume.",
3488 		 function );
3489 
3490 		return( -1 );
3491 	}
3492 	internal_volume = (libfsapfs_internal_volume_t *) volume;
3493 
3494 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3495 	if( libcthreads_read_write_lock_grab_for_read(
3496 	     internal_volume->read_write_lock,
3497 	     error ) != 1 )
3498 	{
3499 		libcerror_error_set(
3500 		 error,
3501 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3502 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3503 		 "%s: unable to grab read/write lock for reading.",
3504 		 function );
3505 
3506 		return( -1 );
3507 	}
3508 #endif
3509 	if( libcdata_array_get_number_of_entries(
3510 	     internal_volume->snapshots,
3511 	     number_of_snapshots,
3512 	     error ) != 1 )
3513 	{
3514 		libcerror_error_set(
3515 		 error,
3516 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3517 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3518 		 "%s: unable to retrieve number of entries from snapshots array.",
3519 		 function );
3520 
3521 		result = -1;
3522 	}
3523 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3524 	if( libcthreads_read_write_lock_release_for_read(
3525 	     internal_volume->read_write_lock,
3526 	     error ) != 1 )
3527 	{
3528 		libcerror_error_set(
3529 		 error,
3530 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3531 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3532 		 "%s: unable to release read/write lock for reading.",
3533 		 function );
3534 
3535 		return( -1 );
3536 	}
3537 #endif
3538 	return( result );
3539 }
3540 
3541 /* Retrieves a specific of snapshot
3542  * The snapshot reference must be freed after use with libfsapfs_snapshot_free
3543  * Returns 1 if successful or -1 on error
3544  */
libfsapfs_volume_get_snapshot_by_index(libfsapfs_volume_t * volume,int snapshot_index,libfsapfs_snapshot_t ** snapshot,libcerror_error_t ** error)3545 int libfsapfs_volume_get_snapshot_by_index(
3546      libfsapfs_volume_t *volume,
3547      int snapshot_index,
3548      libfsapfs_snapshot_t **snapshot,
3549      libcerror_error_t **error )
3550 {
3551 	libfsapfs_internal_volume_t *internal_volume     = NULL;
3552 	libfsapfs_snapshot_metadata_t *snapshot_metadata = NULL;
3553 	static char *function                            = "libfsapfs_volume_get_snapshot_by_index";
3554 	off64_t file_offset                              = 0;
3555 
3556 	if( volume == NULL )
3557 	{
3558 		libcerror_error_set(
3559 		 error,
3560 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3561 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3562 		 "%s: invalid volume.",
3563 		 function );
3564 
3565 		return( -1 );
3566 	}
3567 	internal_volume = (libfsapfs_internal_volume_t *) volume;
3568 
3569 	if( snapshot == NULL )
3570 	{
3571 		libcerror_error_set(
3572 		 error,
3573 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3574 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3575 		 "%s: invalid snapshot.",
3576 		 function );
3577 
3578 		return( -1 );
3579 	}
3580 	if( *snapshot != NULL )
3581 	{
3582 		libcerror_error_set(
3583 		 error,
3584 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3585 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
3586 		 "%s: invalid snapshot value already set.",
3587 		 function );
3588 
3589 		return( -1 );
3590 	}
3591 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3592 	if( libcthreads_read_write_lock_grab_for_read(
3593 	     internal_volume->read_write_lock,
3594 	     error ) != 1 )
3595 	{
3596 		libcerror_error_set(
3597 		 error,
3598 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3599 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3600 		 "%s: unable to grab read/write lock for reading.",
3601 		 function );
3602 
3603 		return( -1 );
3604 	}
3605 #endif
3606 	if( libcdata_array_get_entry_by_index(
3607 	     internal_volume->snapshots,
3608 	     snapshot_index,
3609 	     (intptr_t **) &snapshot_metadata,
3610 	     error ) != 1 )
3611 	{
3612 		libcerror_error_set(
3613 		 error,
3614 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3615 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3616 		 "%s: unable to retrieve snapshot metadata: %d.",
3617 		 function,
3618 		 snapshot_index );
3619 
3620 		return( -1 );
3621 	}
3622 	if( snapshot_metadata == NULL )
3623 	{
3624 		libcerror_error_set(
3625 		 error,
3626 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3627 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
3628 		 "%s: invalid snapshot metadata: %d.",
3629 		 function,
3630 		 snapshot_index );
3631 
3632 		goto on_error;
3633 	}
3634 	if( libfsapfs_snapshot_initialize(
3635 	     snapshot,
3636 	     internal_volume->io_handle,
3637 	     internal_volume->file_io_handle,
3638 	     snapshot_metadata,
3639 	     error ) != 1 )
3640 	{
3641 		libcerror_error_set(
3642 		 error,
3643 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3644 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3645 		 "%s: unable to create snapshot.",
3646 		 function );
3647 
3648 		goto on_error;
3649 	}
3650 	file_offset = (off64_t) ( snapshot_metadata->volume_superblock_block_number * internal_volume->io_handle->block_size );
3651 
3652 	if( libfsapfs_internal_snapshot_open_read(
3653 	     (libfsapfs_internal_snapshot_t *) *snapshot,
3654 	     internal_volume->file_io_handle,
3655 	     file_offset,
3656 	     error ) != 1 )
3657 	{
3658 		libcerror_error_set(
3659 		 error,
3660 		 LIBCERROR_ERROR_DOMAIN_IO,
3661 		 LIBCERROR_IO_ERROR_OPEN_FAILED,
3662 		 "%s: unable to open snapshot: %d.",
3663 		 function,
3664 		 snapshot_index );
3665 
3666 		goto on_error;
3667 	}
3668 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3669 	if( libcthreads_read_write_lock_release_for_read(
3670 	     internal_volume->read_write_lock,
3671 	     error ) != 1 )
3672 	{
3673 		libcerror_error_set(
3674 		 error,
3675 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
3676 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3677 		 "%s: unable to release read/write lock for reading.",
3678 		 function );
3679 
3680 		return( -1 );
3681 	}
3682 #endif
3683 	return( 1 );
3684 
3685 on_error:
3686 	if( *snapshot != NULL )
3687 	{
3688 		libfsapfs_snapshot_free(
3689 		 snapshot,
3690 		 NULL );
3691 	}
3692 #if defined( HAVE_LIBFSAPFS_MULTI_THREAD_SUPPORT )
3693 	libcthreads_read_write_lock_release_for_read(
3694 	 internal_volume->read_write_lock,
3695 	 NULL );
3696 #endif
3697 	return( -1 );
3698 }
3699 
3700