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