1 /*
2  * Mount file system
3  *
4  * Copyright (C) 2013-2020, 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 <system_string.h>
26 #include <types.h>
27 #include <wide_string.h>
28 
29 #if defined( HAVE_SYS_STAT_H )
30 #include <sys/stat.h>
31 #endif
32 
33 #if defined( TIME_WITH_SYS_TIME )
34 #include <sys/time.h>
35 #include <time.h>
36 #elif defined( HAVE_SYS_TIME_H )
37 #include <sys/time.h>
38 #else
39 #include <time.h>
40 #endif
41 
42 #include "luksdetools_libcdata.h"
43 #include "luksdetools_libcerror.h"
44 #include "luksdetools_libluksde.h"
45 #include "mount_file_system.h"
46 
47 /* Creates a file system
48  * Make sure the value file_system is referencing, is set to NULL
49  * Returns 1 if successful or -1 on error
50  */
mount_file_system_initialize(mount_file_system_t ** file_system,libcerror_error_t ** error)51 int mount_file_system_initialize(
52      mount_file_system_t **file_system,
53      libcerror_error_t **error )
54 {
55 #if defined( WINAPI )
56 	FILETIME filetime;
57 	SYSTEMTIME systemtime;
58 
59 #elif defined( HAVE_CLOCK_GETTIME )
60 	struct timespec time_structure;
61 #endif
62 
63 	static char *function = "mount_file_system_initialize";
64 
65 #if defined( WINAPI )
66 	DWORD error_code      = 0;
67 #else
68 	int64_t timestamp     = 0;
69 #endif
70 
71 	if( file_system == NULL )
72 	{
73 		libcerror_error_set(
74 		 error,
75 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
76 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
77 		 "%s: invalid file system.",
78 		 function );
79 
80 		return( -1 );
81 	}
82 	if( *file_system != NULL )
83 	{
84 		libcerror_error_set(
85 		 error,
86 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
87 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
88 		 "%s: invalid file system value already set.",
89 		 function );
90 
91 		return( -1 );
92 	}
93 	*file_system = memory_allocate_structure(
94 	                mount_file_system_t );
95 
96 	if( *file_system == NULL )
97 	{
98 		libcerror_error_set(
99 		 error,
100 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
101 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
102 		 "%s: unable to create file system.",
103 		 function );
104 
105 		goto on_error;
106 	}
107 	if( memory_set(
108 	     *file_system,
109 	     0,
110 	     sizeof( mount_file_system_t ) ) == NULL )
111 	{
112 		libcerror_error_set(
113 		 error,
114 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
115 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
116 		 "%s: unable to clear file system.",
117 		 function );
118 
119 		memory_free(
120 		 *file_system );
121 
122 		*file_system = NULL;
123 
124 		return( -1 );
125 	}
126 	if( libcdata_array_initialize(
127 	     &( ( *file_system )->volumes_array ),
128 	     0,
129 	     error ) != 1 )
130 	{
131 		libcerror_error_set(
132 		 error,
133 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
134 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
135 		 "%s: unable to initialize volumes array.",
136 		 function );
137 
138 		goto on_error;
139 	}
140 #if defined( WINAPI )
141 	if( memory_set(
142 	     &systemtime,
143 	     0,
144 	     sizeof( SYSTEMTIME ) ) == NULL )
145 	{
146 		libcerror_error_set(
147 		 error,
148 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
149 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
150 		 "%s: unable to clear systemtime.",
151 		 function );
152 
153 		goto on_error;
154 	}
155 	GetSystemTime(
156 	 &systemtime );
157 
158 	if( SystemTimeToFileTime(
159 	     &systemtime,
160 	     &filetime ) == 0 )
161 	{
162 		error_code = GetLastError();
163 
164 		libcerror_system_set_error(
165 		 error,
166 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
167 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
168 		 error_code,
169 		 "%s: unable to retrieve FILETIME of current time.",
170 		 function );
171 
172 		goto on_error;
173 	}
174 	( *file_system )->mounted_timestamp = ( (uint64_t) filetime.dwHighDateTime << 32 ) | filetime.dwLowDateTime;
175 
176 #elif defined( HAVE_CLOCK_GETTIME )
177 	if( clock_gettime(
178 	     CLOCK_REALTIME,
179 	     &time_structure ) != 0 )
180 	{
181 		libcerror_error_set(
182 		 error,
183 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
184 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
185 		 "%s: unable to retrieve current time structure.",
186 		 function );
187 
188 		goto on_error;
189 	}
190 	timestamp = ( (int64_t) time_structure.tv_sec * 1000000000 ) + time_structure.tv_nsec;
191 
192 	( *file_system )->mounted_timestamp = (uint64_t) timestamp;
193 
194 #else
195 	timestamp = (int64_t) time( NULL );
196 
197 	if( timestamp == -1 )
198 	{
199 		libcerror_error_set(
200 		 error,
201 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
202 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
203 		 "%s: unable to retrieve current time.",
204 		 function );
205 
206 		goto on_error;
207 	}
208 	timestamp *= 1000000000;
209 
210 	( *file_system )->mounted_timestamp = (uint64_t) timestamp;
211 
212 #endif /* defined( HAVE_CLOCK_GETTIME ) */
213 
214 	return( 1 );
215 
216 on_error:
217 	if( *file_system != NULL )
218 	{
219 		memory_free(
220 		 *file_system );
221 
222 		*file_system = NULL;
223 	}
224 	return( -1 );
225 }
226 
227 /* Frees a file system
228  * Returns 1 if successful or -1 on error
229  */
mount_file_system_free(mount_file_system_t ** file_system,libcerror_error_t ** error)230 int mount_file_system_free(
231      mount_file_system_t **file_system,
232      libcerror_error_t **error )
233 {
234 	static char *function = "mount_file_system_free";
235 	int result            = 1;
236 
237 	if( file_system == NULL )
238 	{
239 		libcerror_error_set(
240 		 error,
241 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
242 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
243 		 "%s: invalid file system.",
244 		 function );
245 
246 		return( -1 );
247 	}
248 	if( *file_system != NULL )
249 	{
250 		if( ( *file_system )->path_prefix != NULL )
251 		{
252 			memory_free(
253 			 ( *file_system )->path_prefix );
254 		}
255 		if( libcdata_array_free(
256 		     &( ( *file_system )->volumes_array ),
257 		     NULL,
258 		     error ) != 1 )
259 		{
260 			libcerror_error_set(
261 			 error,
262 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
263 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
264 			 "%s: unable to free volumes array.",
265 			 function );
266 
267 			result = -1;
268 		}
269 		memory_free(
270 		 *file_system );
271 
272 		*file_system = NULL;
273 	}
274 	return( result );
275 }
276 
277 /* Signals the file system to abort
278  * Returns 1 if successful or -1 on error
279  */
mount_file_system_signal_abort(mount_file_system_t * file_system,libcerror_error_t ** error)280 int mount_file_system_signal_abort(
281      mount_file_system_t *file_system,
282      libcerror_error_t **error )
283 {
284 	libluksde_volume_t *luksde_volume = NULL;
285 	static char *function             = "mount_file_system_signal_abort";
286 	int number_of_volumes             = 0;
287 	int volume_index                  = 0;
288 
289 	if( file_system == NULL )
290 	{
291 		libcerror_error_set(
292 		 error,
293 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
294 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
295 		 "%s: invalid file system.",
296 		 function );
297 
298 		return( -1 );
299 	}
300 	if( libcdata_array_get_number_of_entries(
301 	     file_system->volumes_array,
302 	     &number_of_volumes,
303 	     error ) != 1 )
304 	{
305 		libcerror_error_set(
306 		 error,
307 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
308 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
309 		 "%s: unable to retrieve number of volumes.",
310 		 function );
311 
312 		return( -1 );
313 	}
314 	for( volume_index = number_of_volumes - 1;
315 	     volume_index > 0;
316 	     volume_index-- )
317 	{
318 		if( libcdata_array_get_entry_by_index(
319 		     file_system->volumes_array,
320 		     volume_index,
321 		     (intptr_t **) &luksde_volume,
322 		     error ) != 1 )
323 		{
324 			libcerror_error_set(
325 			 error,
326 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
327 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
328 			 "%s: unable to retrieve volume: %d.",
329 			 function,
330 			 volume_index );
331 
332 			return( -1 );
333 		}
334 		if( libluksde_volume_signal_abort(
335 		     luksde_volume,
336 		     error ) != 1 )
337 		{
338 			libcerror_error_set(
339 			 error,
340 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
341 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
342 			 "%s: unable to signal volume: %d to abort.",
343 			 function,
344 			 volume_index );
345 
346 			return( -1 );
347 		}
348 	}
349 	return( 1 );
350 }
351 
352 /* Sets the path prefix
353  * Returns 1 if successful or -1 on error
354  */
mount_file_system_set_path_prefix(mount_file_system_t * file_system,const system_character_t * path_prefix,size_t path_prefix_size,libcerror_error_t ** error)355 int mount_file_system_set_path_prefix(
356      mount_file_system_t *file_system,
357      const system_character_t *path_prefix,
358      size_t path_prefix_size,
359      libcerror_error_t **error )
360 {
361 	static char *function = "mount_file_system_set_path_prefix";
362 
363 	if( file_system == NULL )
364 	{
365 		libcerror_error_set(
366 		 error,
367 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
368 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
369 		 "%s: invalid file system.",
370 		 function );
371 
372 		return( -1 );
373 	}
374 	if( file_system->path_prefix != NULL )
375 	{
376 		libcerror_error_set(
377 		 error,
378 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
379 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
380 		 "%s: invalid file system - path prefix value already set.",
381 		 function );
382 
383 		return( -1 );
384 	}
385 	if( path_prefix == NULL )
386 	{
387 		libcerror_error_set(
388 		 error,
389 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
390 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
391 		 "%s: invalid path prefix.",
392 		 function );
393 
394 		return( -1 );
395 	}
396 	if( path_prefix_size == 0 )
397 	{
398 		libcerror_error_set(
399 		 error,
400 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
401 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
402 		 "%s: missing path prefix.",
403 		 function );
404 
405 		goto on_error;
406 	}
407 	if( path_prefix_size > (size_t) ( SSIZE_MAX / sizeof( system_character_t ) ) )
408 	{
409 		libcerror_error_set(
410 		 error,
411 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
412 		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
413 		 "%s: invalid path prefix size value exceeds maximum.",
414 		 function );
415 
416 		goto on_error;
417 	}
418 	file_system->path_prefix = system_string_allocate(
419 	                            path_prefix_size );
420 
421 	if( file_system->path_prefix == NULL )
422 	{
423 		libcerror_error_set(
424 		 error,
425 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
426 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
427 		 "%s: unable to create path prefix string.",
428 		 function );
429 
430 		goto on_error;
431 	}
432 	if( system_string_copy(
433 	     file_system->path_prefix,
434 	     path_prefix,
435 	     path_prefix_size ) == NULL )
436 	{
437 		libcerror_error_set(
438 		 error,
439 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
440 		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
441 		 "%s: unable to copy path prefix.",
442 		 function );
443 
444 		goto on_error;
445 	}
446 	file_system->path_prefix[ path_prefix_size - 1 ] = 0;
447 
448 	file_system->path_prefix_size = path_prefix_size;
449 
450 	return( 1 );
451 
452 on_error:
453 	if( file_system->path_prefix != NULL )
454 	{
455 		memory_free(
456 		 file_system->path_prefix );
457 
458 		file_system->path_prefix = NULL;
459 	}
460 	file_system->path_prefix_size = 0;
461 
462 	return( -1 );
463 }
464 
465 /* Retrieves the mounted timestamp
466  * On Windows the timestamp is an unsigned 64-bit FILETIME timestamp
467  * otherwise the timestamp is a signed 64-bit POSIX date and time value in number of nanoseconds
468  * Returns 1 if successful or -1 on error
469  */
mount_file_system_get_mounted_timestamp(mount_file_system_t * file_system,uint64_t * mounted_timestamp,libcerror_error_t ** error)470 int mount_file_system_get_mounted_timestamp(
471      mount_file_system_t *file_system,
472      uint64_t *mounted_timestamp,
473      libcerror_error_t **error )
474 {
475 	static char *function = "mount_file_system_get_mounted_timestamp";
476 
477 	if( file_system == NULL )
478 	{
479 		libcerror_error_set(
480 		 error,
481 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
482 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
483 		 "%s: invalid file system.",
484 		 function );
485 
486 		return( -1 );
487 	}
488 	if( mounted_timestamp == NULL )
489 	{
490 		libcerror_error_set(
491 		 error,
492 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
493 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
494 		 "%s: invalid mounted timestamp.",
495 		 function );
496 
497 		return( -1 );
498 	}
499 	*mounted_timestamp = file_system->mounted_timestamp;
500 
501 	return( 1 );
502 }
503 
504 /* Retrieves the number of volumes
505  * Returns 1 if successful or -1 on error
506  */
mount_file_system_get_number_of_volumes(mount_file_system_t * file_system,int * number_of_volumes,libcerror_error_t ** error)507 int mount_file_system_get_number_of_volumes(
508      mount_file_system_t *file_system,
509      int *number_of_volumes,
510      libcerror_error_t **error )
511 {
512 	static char *function = "mount_file_system_get_number_of_volumes";
513 
514 	if( file_system == NULL )
515 	{
516 		libcerror_error_set(
517 		 error,
518 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
519 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
520 		 "%s: invalid file system.",
521 		 function );
522 
523 		return( -1 );
524 	}
525 	if( libcdata_array_get_number_of_entries(
526 	     file_system->volumes_array,
527 	     number_of_volumes,
528 	     error ) != 1 )
529 	{
530 		libcerror_error_set(
531 		 error,
532 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
533 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
534 		 "%s: unable to retrieve number of volumes.",
535 		 function );
536 
537 		return( -1 );
538 	}
539 	return( 1 );
540 }
541 
542 /* Retrieves a specific volume
543  * Returns 1 if successful or -1 on error
544  */
mount_file_system_get_volume_by_index(mount_file_system_t * file_system,int volume_index,libluksde_volume_t ** luksde_volume,libcerror_error_t ** error)545 int mount_file_system_get_volume_by_index(
546      mount_file_system_t *file_system,
547      int volume_index,
548      libluksde_volume_t **luksde_volume,
549      libcerror_error_t **error )
550 {
551 	static char *function = "mount_file_system_get_volume_by_index";
552 
553 	if( file_system == NULL )
554 	{
555 		libcerror_error_set(
556 		 error,
557 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
558 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
559 		 "%s: invalid file system.",
560 		 function );
561 
562 		return( -1 );
563 	}
564 	if( libcdata_array_get_entry_by_index(
565 	     file_system->volumes_array,
566 	     volume_index,
567 	     (intptr_t **) luksde_volume,
568 	     error ) != 1 )
569 	{
570 		libcerror_error_set(
571 		 error,
572 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
573 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
574 		 "%s: unable to retrieve volume: %d.",
575 		 function,
576 		 volume_index );
577 
578 		return( -1 );
579 	}
580 	return( 1 );
581 }
582 
583 /* Retrieves the volume for a specific path
584  * Returns 1 if successful, 0 if no such volume or -1 on error
585  */
mount_file_system_get_volume_by_path(mount_file_system_t * file_system,const system_character_t * path,size_t path_length,libluksde_volume_t ** luksde_volume,libcerror_error_t ** error)586 int mount_file_system_get_volume_by_path(
587      mount_file_system_t *file_system,
588      const system_character_t *path,
589      size_t path_length,
590      libluksde_volume_t **luksde_volume,
591      libcerror_error_t **error )
592 {
593 	static char *function        = "mount_file_system_get_volume_by_path";
594 	system_character_t character = 0;
595 	size_t path_index            = 0;
596 	int result                   = 0;
597 	int volume_index             = 0;
598 
599 	if( file_system == NULL )
600 	{
601 		libcerror_error_set(
602 		 error,
603 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
604 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
605 		 "%s: invalid file system.",
606 		 function );
607 
608 		return( -1 );
609 	}
610 	if( file_system->path_prefix == NULL )
611 	{
612 		libcerror_error_set(
613 		 error,
614 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
615 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
616 		 "%s: invalid file system - missing path prefix.",
617 		 function );
618 
619 		return( -1 );
620 	}
621 	if( path == NULL )
622 	{
623 		libcerror_error_set(
624 		 error,
625 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
626 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
627 		 "%s: invalid path.",
628 		 function );
629 
630 		return( -1 );
631 	}
632 	if( path_length > (size_t) ( SSIZE_MAX - 1 ) )
633 	{
634 		libcerror_error_set(
635 		 error,
636 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
637 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
638 		 "%s: invalid path length value exceeds maximum.",
639 		 function );
640 
641 		return( -1 );
642 	}
643 	if( luksde_volume == NULL )
644 	{
645 		libcerror_error_set(
646 		 error,
647 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
648 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
649 		 "%s: invalid volume.",
650 		 function );
651 
652 		return( -1 );
653 	}
654 	path_length = system_string_length(
655 	               path );
656 
657 	if( ( path_length == 1 )
658 	 && ( path[ 0 ] == file_system->path_prefix[ 0 ] ) )
659 	{
660 		*luksde_volume = NULL;
661 
662 		return( 1 );
663 	}
664 	if( ( path_length < file_system->path_prefix_size )
665 	 || ( path_length > ( file_system->path_prefix_size + 3 ) ) )
666 	{
667 		return( 0 );
668 	}
669 #if defined( WINAPI )
670 	result = system_string_compare_no_case(
671 	          path,
672 	          file_system->path_prefix,
673 	          file_system->path_prefix_size - 1 );
674 #else
675 	result = system_string_compare(
676 	          path,
677 	          file_system->path_prefix,
678 	          file_system->path_prefix_size - 1 );
679 #endif
680 	if( result != 0 )
681 	{
682 		return( 0 );
683 	}
684 	volume_index = 0;
685 
686 	path_index = file_system->path_prefix_size - 1;
687 
688 	while( path_index < path_length )
689 	{
690 		character = path[ path_index++ ];
691 
692 		if( ( character < (system_character_t) '0' )
693 		 || ( character > (system_character_t) '9' ) )
694 		{
695 			return( 0 );
696 		}
697 		volume_index *= 10;
698 		volume_index += character - (system_character_t) '0';
699 	}
700 	volume_index -= 1;
701 
702 	if( libcdata_array_get_entry_by_index(
703 	     file_system->volumes_array,
704 	     volume_index,
705 	     (intptr_t **) luksde_volume,
706 	     error ) != 1 )
707 	{
708 		libcerror_error_set(
709 		 error,
710 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
711 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
712 		 "%s: unable to retrieve volume: %d.",
713 		 function,
714 		 volume_index );
715 
716 		return( -1 );
717 	}
718 	return( 1 );
719 }
720 
721 /* Appends a volume to the file system
722  * Returns 1 if successful or -1 on error
723  */
mount_file_system_append_volume(mount_file_system_t * file_system,libluksde_volume_t * luksde_volume,libcerror_error_t ** error)724 int mount_file_system_append_volume(
725      mount_file_system_t *file_system,
726      libluksde_volume_t *luksde_volume,
727      libcerror_error_t **error )
728 {
729 	static char *function = "mount_file_system_append_volume";
730 	int entry_index       = 0;
731 
732 	if( file_system == NULL )
733 	{
734 		libcerror_error_set(
735 		 error,
736 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
737 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
738 		 "%s: invalid file system.",
739 		 function );
740 
741 		return( -1 );
742 	}
743 	if( libcdata_array_append_entry(
744 	     file_system->volumes_array,
745 	     &entry_index,
746 	     (intptr_t *) luksde_volume,
747 	     error ) != 1 )
748 	{
749 		libcerror_error_set(
750 		 error,
751 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
752 		 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
753 		 "%s: unable to append volume to array.",
754 		 function );
755 
756 		return( -1 );
757 	}
758 	return( 1 );
759 }
760 
761 /* Retrieves the path from a volume index.
762  * Returns 1 if successful or -1 on error
763  */
mount_file_system_get_path_from_volume_index(mount_file_system_t * file_system,int volume_index,system_character_t * path,size_t path_size,libcerror_error_t ** error)764 int mount_file_system_get_path_from_volume_index(
765      mount_file_system_t *file_system,
766      int volume_index,
767      system_character_t *path,
768      size_t path_size,
769      libcerror_error_t **error )
770 {
771 	static char *function     = "mount_file_system_get_path_from_volume_index";
772 	size_t path_index         = 0;
773 	size_t required_path_size = 0;
774 	int volume_number         = 0;
775 
776 	if( file_system == NULL )
777 	{
778 		libcerror_error_set(
779 		 error,
780 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
781 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
782 		 "%s: invalid file system.",
783 		 function );
784 
785 		return( -1 );
786 	}
787 	if( file_system->path_prefix == NULL )
788 	{
789 		libcerror_error_set(
790 		 error,
791 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
792 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
793 		 "%s: invalid file system - missing path prefix.",
794 		 function );
795 
796 		return( -1 );
797 	}
798 	if( path == NULL )
799 	{
800 		libcerror_error_set(
801 		 error,
802 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
803 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
804 		 "%s: invalid path.",
805 		 function );
806 
807 		return( -1 );
808 	}
809 	if( path_size > (size_t) SSIZE_MAX )
810 	{
811 		libcerror_error_set(
812 		 error,
813 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
815 		 "%s: invalid path length value exceeds maximum.",
816 		 function );
817 
818 		return( -1 );
819 	}
820         required_path_size = file_system->path_prefix_size;
821 
822 	volume_number = volume_index + 1;
823 
824 	while( volume_number > 0 )
825 	{
826 		required_path_size++;
827 
828 		volume_number /= 10;
829 	}
830 	if( path_size <= required_path_size )
831 	{
832 		libcerror_error_set(
833 		 error,
834 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
835 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
836 		 "%s: invalid path size value too small.",
837 		 function );
838 
839 		return( -1 );
840 	}
841 	if( system_string_copy(
842 	     path,
843 	     file_system->path_prefix,
844 	     file_system->path_prefix_size ) == NULL )
845 	{
846 		libcerror_error_set(
847 		 error,
848 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
849 		 LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
850 		 "%s: unable to copy path prefix.",
851 		 function );
852 
853 		return( -1 );
854 	}
855 	path_index = required_path_size - 1;
856 
857 	volume_number = volume_index + 1;
858 
859 	path[ path_index-- ] = 0;
860 
861 	while( volume_number > 0 )
862 	{
863 		path[ path_index-- ] = (system_character_t) '0' + ( volume_number % 10 );
864 
865 		volume_number /= 10;
866 	}
867 	return( 1 );
868 }
869 
870