1 /*
2  * File system functions
3  *
4  * Copyright (C) 2010-2021, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #include "libfsntfs_cluster_block.h"
28 #include "libfsntfs_cluster_block_vector.h"
29 #include "libfsntfs_definitions.h"
30 #include "libfsntfs_file_system.h"
31 #include "libfsntfs_libbfio.h"
32 #include "libfsntfs_libcdata.h"
33 #include "libfsntfs_libcerror.h"
34 #include "libfsntfs_libcnotify.h"
35 #include "libfsntfs_libcthreads.h"
36 #include "libfsntfs_libuna.h"
37 #include "libfsntfs_mft.h"
38 #include "libfsntfs_mft_attribute_list.h"
39 #include "libfsntfs_mft_entry.h"
40 #include "libfsntfs_name.h"
41 #include "libfsntfs_path_hint.h"
42 #include "libfsntfs_security_descriptor_index.h"
43 #include "libfsntfs_security_descriptor_values.h"
44 
45 /* Creates a file system
46  * Make sure the value file_system is referencing, is set to NULL
47  * Returns 1 if successful or -1 on error
48  */
libfsntfs_file_system_initialize(libfsntfs_file_system_t ** file_system,libcerror_error_t ** error)49 int libfsntfs_file_system_initialize(
50      libfsntfs_file_system_t **file_system,
51      libcerror_error_t **error )
52 {
53 	static char *function = "libfsntfs_file_system_initialize";
54 
55 	if( file_system == NULL )
56 	{
57 		libcerror_error_set(
58 		 error,
59 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61 		 "%s: invalid file system.",
62 		 function );
63 
64 		return( -1 );
65 	}
66 	if( *file_system != NULL )
67 	{
68 		libcerror_error_set(
69 		 error,
70 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
71 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72 		 "%s: invalid file system value already set.",
73 		 function );
74 
75 		return( -1 );
76 	}
77 	*file_system = memory_allocate_structure(
78 	                libfsntfs_file_system_t );
79 
80 	if( *file_system == NULL )
81 	{
82 		libcerror_error_set(
83 		 error,
84 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
85 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86 		 "%s: unable to create file system.",
87 		 function );
88 
89 		goto on_error;
90 	}
91 	if( memory_set(
92 	     *file_system,
93 	     0,
94 	     sizeof( libfsntfs_file_system_t ) ) == NULL )
95 	{
96 		libcerror_error_set(
97 		 error,
98 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
99 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
100 		 "%s: unable to clear file system.",
101 		 function );
102 
103 		memory_free(
104 		 *file_system );
105 
106 		*file_system = NULL;
107 
108 		return( -1 );
109 	}
110 #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT )
111 	if( libcthreads_read_write_lock_initialize(
112 	     &( ( *file_system )->read_write_lock ),
113 	     error ) != 1 )
114 	{
115 		libcerror_error_set(
116 		 error,
117 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
118 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
119 		 "%s: unable to initialize read/write lock.",
120 		 function );
121 
122 		goto on_error;
123 	}
124 #endif
125 	return( 1 );
126 
127 on_error:
128 	if( *file_system != NULL )
129 	{
130 		memory_free(
131 		 *file_system );
132 
133 		*file_system = NULL;
134 	}
135 	return( -1 );
136 }
137 
138 /* Frees a file system
139  * Returns 1 if successful or -1 on error
140  */
libfsntfs_file_system_free(libfsntfs_file_system_t ** file_system,libcerror_error_t ** error)141 int libfsntfs_file_system_free(
142      libfsntfs_file_system_t **file_system,
143      libcerror_error_t **error )
144 {
145 	static char *function = "libfsntfs_file_system_free";
146 	int result            = 1;
147 
148 	if( file_system == NULL )
149 	{
150 		libcerror_error_set(
151 		 error,
152 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
153 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
154 		 "%s: invalid file system.",
155 		 function );
156 
157 		return( -1 );
158 	}
159 	if( *file_system != NULL )
160 	{
161 #if defined( HAVE_LIBFSNTFS_MULTI_THREAD_SUPPORT )
162 		if( libcthreads_read_write_lock_free(
163 		     &( ( *file_system )->read_write_lock ),
164 		     error ) != 1 )
165 		{
166 			libcerror_error_set(
167 			 error,
168 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
169 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
170 			 "%s: unable to free read/write lock.",
171 			 function );
172 
173 			result = -1;
174 		}
175 #endif
176 		if( ( *file_system )->path_hints_tree != NULL )
177 		{
178 			if( libcdata_btree_free(
179 			     &( ( *file_system )->path_hints_tree ),
180 			     (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free,
181 			     error ) != 1 )
182 			{
183 				libcerror_error_set(
184 				 error,
185 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
186 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
187 				 "%s: unable to free path hints tree.",
188 				 function );
189 
190 				result = -1;
191 			}
192 		}
193 		if( ( *file_system )->security_descriptor_index != NULL )
194 		{
195 			if( libfsntfs_security_descriptor_index_free(
196 			     &( ( *file_system )->security_descriptor_index ),
197 			     error ) != 1 )
198 			{
199 				libcerror_error_set(
200 				 error,
201 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
202 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
203 				 "%s: unable to free security descriptor index.",
204 				 function );
205 
206 				result = -1;
207 			}
208 		}
209 		if( ( *file_system )->mft != NULL )
210 		{
211 			if( libfsntfs_mft_free(
212 			     &( ( *file_system )->mft ),
213 			     error ) != 1 )
214 			{
215 				libcerror_error_set(
216 				 error,
217 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
218 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
219 				 "%s: unable to free MFT.",
220 				 function );
221 
222 				result = -1;
223 			}
224 		}
225 		memory_free(
226 		 *file_system );
227 
228 		*file_system = NULL;
229 	}
230 	return( result );
231 }
232 
233 /* Reads the MFT
234  * Returns 1 if successful or -1 on error
235  */
libfsntfs_file_system_read_mft(libfsntfs_file_system_t * file_system,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,off64_t mft_offset,uint8_t flags,libcerror_error_t ** error)236 int libfsntfs_file_system_read_mft(
237      libfsntfs_file_system_t *file_system,
238      libfsntfs_io_handle_t *io_handle,
239      libbfio_handle_t *file_io_handle,
240      off64_t mft_offset,
241      uint8_t flags,
242      libcerror_error_t **error )
243 {
244 	libfsntfs_data_run_t *data_run                 = NULL;
245 	libfsntfs_mft_attribute_t *data_attribute      = NULL;
246 	libfsntfs_mft_attribute_t *last_data_attribute = NULL;
247 	libfsntfs_mft_entry_t *mft_entry               = NULL;
248 	static char *function                          = "libfsntfs_file_system_read_mft";
249 	size64_t mft_size                              = 0;
250 	uint64_t file_reference                        = 0;
251 	uint64_t number_of_mft_entries                 = 0;
252 	uint16_t attribute_data_flags                  = 0;
253 	int attribute_index                            = 0;
254 	int data_run_index                             = 0;
255 	int file_reference_index                       = 0;
256 	int number_of_data_runs                        = 0;
257 	int number_of_file_entries                     = 0;
258 	int segment_index                              = 0;
259 
260 	if( file_system == NULL )
261 	{
262 		libcerror_error_set(
263 		 error,
264 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
265 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
266 		 "%s: invalid file system.",
267 		 function );
268 
269 		return( -1 );
270 	}
271 	if( file_system->mft != NULL )
272 	{
273 		libcerror_error_set(
274 		 error,
275 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
276 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
277 		 "%s: invalid file system - MFT value already set.",
278 		 function );
279 
280 		return( -1 );
281 	}
282 	if( io_handle == NULL )
283 	{
284 		libcerror_error_set(
285 		 error,
286 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288 		 "%s: invalid IO handle.",
289 		 function );
290 
291 		return( -1 );
292 	}
293 	if( mft_offset < 0 )
294 	{
295 		libcerror_error_set(
296 		 error,
297 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
298 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
299 		 "%s: invalid MFT offset value out of bounds.",
300 		 function );
301 
302 		goto on_error;
303 	}
304 	if( mft_size > (size64_t) INT64_MAX )
305 	{
306 		libcerror_error_set(
307 		 error,
308 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
309 		 LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
310 		 "%s: invalid MFT size value exceeds maximum.",
311 		 function );
312 
313 		return( -1 );
314 	}
315 	if( libfsntfs_mft_entry_initialize(
316 	     &mft_entry,
317 	     error ) != 1 )
318 	{
319 		libcerror_error_set(
320 		 error,
321 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
322 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
323 		 "%s: unable to create MFT entry.",
324 		 function );
325 
326 		goto on_error;
327 	}
328 	if( libfsntfs_mft_entry_read_file_io_handle(
329 	     mft_entry,
330 	     file_io_handle,
331 	     mft_offset,
332 	     io_handle->mft_entry_size,
333 	     LIBFSNTFS_MFT_ENTRY_INDEX_MFT,
334 	     error ) != 1 )
335 	{
336 		libcerror_error_set(
337 		 error,
338 		 LIBCERROR_ERROR_DOMAIN_IO,
339 		 LIBCERROR_IO_ERROR_READ_FAILED,
340 		 "%s: unable to read MFT entry: %d.",
341 		 function,
342 		 LIBFSNTFS_MFT_ENTRY_INDEX_MFT );
343 
344 		goto on_error;
345 	}
346 	if( mft_entry->is_empty == 0 )
347 	{
348 		if( libfsntfs_mft_entry_read_attributes_data(
349 		     mft_entry,
350 		     io_handle,
351 		     mft_entry->data,
352 		     mft_entry->data_size,
353 		     error ) != 1 )
354 		{
355 			libcerror_error_set(
356 			 error,
357 			 LIBCERROR_ERROR_DOMAIN_IO,
358 			 LIBCERROR_IO_ERROR_READ_FAILED,
359 			 "%s: unable to read attributes of MFT entry: %d.",
360 			 function,
361 			 LIBFSNTFS_MFT_ENTRY_INDEX_MFT );
362 
363 			goto on_error;
364 		}
365 	}
366 	if( libfsntfs_mft_attribute_get_data_flags(
367 	     mft_entry->data_attribute,
368 	     &attribute_data_flags,
369 	     error ) != 1 )
370 	{
371 		libcerror_error_set(
372 		 error,
373 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
374 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
375 		 "%s: unable to retrieve attribute data flags.",
376 		 function );
377 
378 		goto on_error;
379 	}
380 	if( ( attribute_data_flags & LIBFSNTFS_ATTRIBUTE_FLAG_COMPRESSION_MASK ) != 0 )
381 	{
382 		libcerror_error_set(
383 		 error,
384 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
385 		 LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
386 		 "%s: unsupported compressed attribute data.",
387 		 function );
388 
389 		goto on_error;
390 	}
391 	if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 )
392 	{
393 		if( libbfio_handle_get_size(
394 		     file_io_handle,
395 		     &mft_size,
396 		     error ) != 1 )
397 		{
398 			libcerror_error_set(
399 			 error,
400 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
401 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
402 			 "%s: unable to retrieve $MFT metadata file size.",
403 			 function );
404 
405 			goto on_error;
406 		}
407 	}
408 	else
409 	{
410 		if( libfsntfs_mft_attribute_get_data_size(
411 		     mft_entry->data_attribute,
412 		     &mft_size,
413 		     error ) != 1 )
414 		{
415 			libcerror_error_set(
416 			 error,
417 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
418 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
419 			 "%s: unable to retrieve data size of MFT entry: %d.",
420 			 function,
421 			 LIBFSNTFS_MFT_ENTRY_INDEX_MFT );
422 
423 			goto on_error;
424 		}
425 	}
426 	if( libfsntfs_mft_initialize(
427 	     &( file_system->mft ),
428 	     io_handle,
429 	     (size64_t) io_handle->mft_entry_size,
430 	     flags,
431 	     error ) != 1 )
432 	{
433 		libcerror_error_set(
434 		 error,
435 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
436 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
437 		 "%s: unable to create MFT.",
438 		 function );
439 
440 		goto on_error;
441 	}
442 	if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 )
443 	{
444 		if( libfdata_vector_append_segment(
445 		     file_system->mft->mft_entry_vector,
446 		     &segment_index,
447 		     0,
448 		     0,
449 		     mft_size,
450 		     0,
451 		     error ) != 1 )
452 		{
453 			libcerror_error_set(
454 			 error,
455 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
456 			 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
457 			 "%s: unable to append $MFT metadata file range to MFT entry vector.",
458 			 function );
459 
460 			goto on_error;
461 		}
462 	}
463 	else
464 	{
465 		if( libfsntfs_mft_attribute_get_number_of_data_runs(
466 		     mft_entry->data_attribute,
467 		     &number_of_data_runs,
468 		     error ) != 1 )
469 		{
470 			libcerror_error_set(
471 			 error,
472 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
473 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
474 			 "%s: unable to retrieve number of data runs.",
475 			 function );
476 
477 			goto on_error;
478 		}
479 		for( data_run_index = 0;
480 		     data_run_index < number_of_data_runs;
481 		     data_run_index++ )
482 		{
483 			if( libfsntfs_mft_attribute_get_data_run_by_index(
484 			     mft_entry->data_attribute,
485 			     data_run_index,
486 			     &data_run,
487 			     error ) != 1 )
488 			{
489 				libcerror_error_set(
490 				 error,
491 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
492 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
493 				 "%s: unable to data run: %d.",
494 				 function,
495 				 data_run_index );
496 
497 				goto on_error;
498 			}
499 			if( data_run == NULL )
500 			{
501 				libcerror_error_set(
502 				 error,
503 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
504 				 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
505 				 "%s: missing data run: %d.",
506 				 data_run_index );
507 
508 				goto on_error;
509 			}
510 			if( libfdata_vector_append_segment(
511 			     file_system->mft->mft_entry_vector,
512 			     &segment_index,
513 			     0,
514 			     data_run->start_offset,
515 			     data_run->size,
516 			     0,
517 			     error ) != 1 )
518 			{
519 				libcerror_error_set(
520 				 error,
521 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
522 				 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
523 				 "%s: unable to append data run: %d to MFT entry vector.",
524 				 function,
525 				 data_run_index );
526 
527 				goto on_error;
528 			}
529 		}
530 		last_data_attribute = mft_entry->data_attribute;
531 	}
532 	if( mft_entry->list_attribute != NULL )
533 	{
534 		if( libfsntfs_mft_entry_read_attribute_list(
535 		     mft_entry,
536 		     io_handle,
537 		     file_io_handle,
538 		     error ) != 1 )
539 		{
540 			libcerror_error_set(
541 			 error,
542 			 LIBCERROR_ERROR_DOMAIN_IO,
543 			 LIBCERROR_IO_ERROR_READ_FAILED,
544 			 "%s: unable to read attribute list.",
545 			 function );
546 
547 			goto on_error;
548 		}
549 		if( libfsntfs_mft_attribute_list_get_number_of_file_references(
550 		     mft_entry->attribute_list,
551 		     &number_of_file_entries,
552 		     error ) != 1 )
553 		{
554 			libcerror_error_set(
555 			 error,
556 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
557 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
558 			 "%s: unable to retrieve number of attribute list data MFT entries.",
559 			 function );
560 
561 			goto on_error;
562 		}
563 		for( file_reference_index = 0;
564 		     file_reference_index < number_of_file_entries;
565 		     file_reference_index++ )
566 		{
567 			if( libfsntfs_mft_attribute_list_get_file_reference_by_index(
568 			     mft_entry->attribute_list,
569 			     file_reference_index,
570 			     &file_reference,
571 			     error ) != 1 )
572 			{
573 				libcerror_error_set(
574 				 error,
575 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
576 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
577 				 "%s: unable to retrieve attribute list data MFT entry: %d.",
578 				 function,
579 				 file_reference_index );
580 
581 				goto on_error;
582 			}
583 			if( libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(
584 			     mft_entry,
585 			     io_handle,
586 			     file_io_handle,
587 			     file_system->mft->mft_entry_vector,
588 			     file_system->mft->mft_entry_cache,
589 			     file_reference,
590 			     error ) != 1 )
591 			{
592 				libcerror_error_set(
593 				 error,
594 				 LIBCERROR_ERROR_DOMAIN_IO,
595 				 LIBCERROR_IO_ERROR_READ_FAILED,
596 				 "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".",
597 				 function,
598 				 file_reference & 0xffffffffffffUL,
599 				 file_reference >> 48 );
600 
601 				goto on_error;
602 			}
603 			if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) == 0 )
604 			{
605 				if( libfsntfs_mft_attribute_get_next_attribute(
606 				     last_data_attribute,
607 				     &data_attribute,
608 				     error ) != 1 )
609 				{
610 					libcerror_error_set(
611 					 error,
612 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
613 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
614 					 "%s: unable to retrieve next data attribute: %d.",
615 					 function,
616 					 attribute_index );
617 
618 					goto on_error;
619 				}
620 				if( data_attribute != NULL )
621 				{
622 					attribute_index++;
623 
624 					if( libfsntfs_mft_attribute_get_number_of_data_runs(
625 					     data_attribute,
626 					     &number_of_data_runs,
627 					     error ) != 1 )
628 					{
629 						libcerror_error_set(
630 						 error,
631 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
632 						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
633 						 "%s: unable to retrieve number of data runs.",
634 						 function );
635 
636 						goto on_error;
637 					}
638 					for( data_run_index = 0;
639 					     data_run_index < number_of_data_runs;
640 					     data_run_index++ )
641 					{
642 						if( libfsntfs_mft_attribute_get_data_run_by_index(
643 						     data_attribute,
644 						     data_run_index,
645 						     &data_run,
646 						     error ) != 1 )
647 						{
648 							libcerror_error_set(
649 							 error,
650 							 LIBCERROR_ERROR_DOMAIN_RUNTIME,
651 							 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
652 							 "%s: unable to retrieve data run: %d.",
653 							 function,
654 							 data_run_index );
655 
656 							goto on_error;
657 						}
658 						if( data_run == NULL )
659 						{
660 							libcerror_error_set(
661 							 error,
662 							 LIBCERROR_ERROR_DOMAIN_RUNTIME,
663 							 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
664 							 "%s: missing data run: %d.",
665 							 data_run_index );
666 
667 							goto on_error;
668 						}
669 						if( libfdata_vector_append_segment(
670 						     file_system->mft->mft_entry_vector,
671 						     &segment_index,
672 						     0,
673 						     data_run->start_offset,
674 						     data_run->size,
675 						     0,
676 						     error ) != 1 )
677 						{
678 							libcerror_error_set(
679 							 error,
680 							 LIBCERROR_ERROR_DOMAIN_RUNTIME,
681 							 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
682 							 "%s: unable to append data run: %d to MFT entry vector.",
683 							 function,
684 							 data_run_index );
685 
686 							goto on_error;
687 						}
688 					}
689 					last_data_attribute = data_attribute;
690 				}
691 			}
692 		}
693 	}
694 	number_of_mft_entries = (uint64_t) ( mft_size / io_handle->mft_entry_size );
695 
696 	if( number_of_mft_entries > (uint64_t) INT_MAX )
697 	{
698 		libcerror_error_set(
699 		 error,
700 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
701 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
702 		 "%s: invalid number of MFT entries value out of bounds.",
703 		 function );
704 
705 		goto on_error;
706 	}
707 	file_system->mft->number_of_mft_entries = number_of_mft_entries;
708 
709 	if( libfsntfs_mft_entry_free(
710 	     &mft_entry,
711 	     error ) != 1 )
712 	{
713 		libcerror_error_set(
714 		 error,
715 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
716 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
717 		 "%s: unable to free MFT entry.",
718 		 function );
719 
720 		goto on_error;
721 	}
722 	if( libcdata_btree_initialize(
723 	     &( file_system->path_hints_tree ),
724 	     LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES,
725 	     error ) != 1 )
726 	{
727 		libcerror_error_set(
728 		 error,
729 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
730 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
731 		 "%s: unable to create path hints B-tree.",
732 		 function );
733 
734 		goto on_error;
735 	}
736 	return( 1 );
737 
738 on_error:
739 	if( file_system->path_hints_tree != NULL )
740 	{
741 		libcdata_btree_free(
742 		 &( file_system->path_hints_tree ),
743 		 (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_path_hint_free,
744 		 NULL );
745 	}
746 	if( mft_entry != NULL )
747 	{
748 		libfsntfs_mft_entry_free(
749 		 &mft_entry,
750 		 NULL );
751 	}
752 	return( -1 );
753 }
754 
755 /* Reads the bitmap file entry
756  * Returns 1 if successful or -1 on error
757  */
libfsntfs_file_system_read_bitmap(libfsntfs_file_system_t * file_system,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)758 int libfsntfs_file_system_read_bitmap(
759      libfsntfs_file_system_t *file_system,
760      libfsntfs_io_handle_t *io_handle,
761      libbfio_handle_t *file_io_handle,
762      libcerror_error_t **error )
763 {
764 	libfcache_cache_t *cluster_block_cache   = NULL;
765 	libfdata_vector_t *cluster_block_vector  = NULL;
766 	libfsntfs_cluster_block_t *cluster_block = NULL;
767 	libfsntfs_mft_entry_t *mft_entry         = NULL;
768 	static char *function                    = "libfsntfs_file_system_read_bitmap";
769 	size_t cluster_block_data_offset         = 0;
770 	off64_t bitmap_offset                    = 0;
771 	off64_t start_offset                     = 0;
772 	uint32_t value_32bit                     = 0;
773 	uint8_t bit_index                        = 0;
774 	int cluster_block_index                  = 0;
775 	int number_of_cluster_blocks             = 0;
776 
777 	if( file_system == NULL )
778 	{
779 		libcerror_error_set(
780 		 error,
781 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
782 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
783 		 "%s: invalid file system.",
784 		 function );
785 
786 		return( -1 );
787 	}
788 	if( io_handle == NULL )
789 	{
790 		libcerror_error_set(
791 		 error,
792 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
793 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
794 		 "%s: invalid IO handle.",
795 		 function );
796 
797 		return( -1 );
798 	}
799 	if( libfsntfs_mft_get_mft_entry_by_index(
800 	     file_system->mft,
801 	     file_io_handle,
802 	     LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP,
803 	     &mft_entry,
804 	     error ) != 1 )
805 	{
806 		libcerror_error_set(
807 		 error,
808 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
809 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
810 		 "%s: unable to retrieve MFT entry: %d.",
811 		 function,
812 		 LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP );
813 
814 		goto on_error;
815 	}
816 	if( mft_entry == NULL )
817 	{
818 		libcerror_error_set(
819 		 error,
820 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
821 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
822 		 "%s: missing MFT entry: %d.",
823 		 function,
824 		 LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP );
825 
826 		goto on_error;
827 	}
828 	if( mft_entry->data_attribute == NULL )
829 	{
830 		libcerror_error_set(
831 		 error,
832 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
833 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
834 		 "%s: invalid MFT entry: %d - missing data attribute.",
835 		 function,
836 		 LIBFSNTFS_MFT_ENTRY_INDEX_BITMAP );
837 
838 		goto on_error;
839 	}
840 	if( libfsntfs_cluster_block_vector_initialize(
841 	     &cluster_block_vector,
842 	     io_handle,
843 	     mft_entry->data_attribute,
844 	     error ) != 1 )
845 	{
846 		libcerror_error_set(
847 		 error,
848 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
849 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
850 		 "%s: unable to create cluster block vector.",
851 		 function );
852 
853 		goto on_error;
854 	}
855 	if( libfcache_cache_initialize(
856 	     &cluster_block_cache,
857 	     1,
858 	     error ) != 1 )
859 	{
860 		libcerror_error_set(
861 		 error,
862 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
863 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
864 		 "%s: unable to create cluster block cache.",
865 		 function );
866 
867 		goto on_error;
868 	}
869 	if( libfdata_vector_get_number_of_elements(
870 	     cluster_block_vector,
871 	     &number_of_cluster_blocks,
872 	     error ) != 1 )
873 	{
874 		libcerror_error_set(
875 		 error,
876 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
877 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
878 		 "%s: unable to retrieve number of cluster blocks.",
879 		 function );
880 
881 		goto on_error;
882 	}
883 	for( cluster_block_index = 0;
884 	     cluster_block_index < number_of_cluster_blocks;
885 	     cluster_block_index++ )
886 	{
887 		if( libfdata_vector_get_element_value_by_index(
888 		     cluster_block_vector,
889 		     (intptr_t *) file_io_handle,
890 		     (libfdata_cache_t *) cluster_block_cache,
891 		     cluster_block_index,
892 		     (intptr_t **) &cluster_block,
893 		     0,
894 		     error ) != 1 )
895 		{
896 			libcerror_error_set(
897 			 error,
898 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
899 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
900 			 "%s: unable to retrieve cluster block: %d from vector.",
901 			 function,
902 			 cluster_block_index );
903 
904 			goto on_error;
905 		}
906 		if( cluster_block == NULL )
907 		{
908 			libcerror_error_set(
909 			 error,
910 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
911 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
912 			 "%s: missing cluster block: %d.",
913 			 function,
914 			 cluster_block_index );
915 
916 			goto on_error;
917 		}
918 		if( cluster_block->data == NULL )
919 		{
920 			libcerror_error_set(
921 			 error,
922 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
923 			 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
924 			 "%s: invalid cluster block: %d - missing data.",
925 			 function,
926 			 cluster_block_index );
927 
928 			goto on_error;
929 		}
930 		if( ( ( cluster_block->data_size % 4 ) != 0 )
931 		 || ( cluster_block->data_size > (size_t) SSIZE_MAX ) )
932 		{
933 			libcerror_error_set(
934 			 error,
935 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
936 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
937 			 "%s: cluster block: %d data size value out of bounds.",
938 			 function,
939 			 cluster_block_index );
940 
941 			goto on_error;
942 		}
943 #if defined( HAVE_DEBUG_OUTPUT )
944 		if( libcnotify_verbose != 0 )
945 		{
946 			libcnotify_printf(
947 			 "%s: bitmap segment: %d data:\n",
948 			 function,
949 			 cluster_block_index );
950 			libcnotify_print_data(
951 			 cluster_block->data,
952 			 cluster_block->data_size,
953 			 LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
954 		}
955 #endif
956 		cluster_block_data_offset = 0;
957 		start_offset              = -1;
958 
959 		while( cluster_block_data_offset < cluster_block->data_size )
960 		{
961 			byte_stream_copy_to_uint32_little_endian(
962 			 &( cluster_block->data[ cluster_block_data_offset ] ),
963 			 value_32bit );
964 
965 			for( bit_index = 0;
966 			     bit_index < 32;
967 			     bit_index++ )
968 			{
969 				if( ( value_32bit & 0x00000001UL ) == 0 )
970 				{
971 					if( start_offset >= 0 )
972 					{
973 #if defined( HAVE_DEBUG_OUTPUT )
974 						if( libcnotify_verbose != 0 )
975 						{
976 							libcnotify_printf(
977 							 "%s: offset range\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n",
978 							 function,
979 							 start_offset,
980 							 bitmap_offset,
981 							 bitmap_offset - start_offset );
982 						}
983 #endif
984 /*
985 						if( libfsntfs_offset_list_append_offset(
986 						     offset_list,
987 						     start_offset,
988 						     bitmap_offset - start_offset,
989 						     1,
990 						     error ) != 1 )
991 						{
992 							libcerror_error_set(
993 							 error,
994 							 LIBCERROR_ERROR_DOMAIN_RUNTIME,
995 							 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
996 							 "%s: unable to append offset range to offset list.",
997 							 function );
998 
999 							goto on_error;
1000 						}
1001 */
1002 						start_offset = -1;
1003 					}
1004 				}
1005 				else
1006 				{
1007 					if( start_offset < 0 )
1008 					{
1009 						start_offset = bitmap_offset;
1010 					}
1011 				}
1012 				bitmap_offset += io_handle->cluster_block_size;
1013 
1014 				value_32bit >>= 1;
1015 			}
1016 			cluster_block_data_offset += 4;
1017 		}
1018 		if( start_offset >= 0 )
1019 		{
1020 #if defined( HAVE_DEBUG_OUTPUT )
1021 			if( libcnotify_verbose != 0 )
1022 			{
1023 				libcnotify_printf(
1024 				 "%s: offset range\t\t\t: 0x%08" PRIx64 " - 0x%08" PRIx64 " (0x%08" PRIx64 ")\n",
1025 				 function,
1026 				 start_offset,
1027 				 bitmap_offset,
1028 				 bitmap_offset - start_offset );
1029 			}
1030 #endif
1031 /* TODO
1032 			if( libfsntfs_offset_list_append_offset(
1033 			     offset_list,
1034 			     start_offset,
1035 			     bitmap_offset - start_offset,
1036 			     1,
1037 			     error ) != 1 )
1038 			{
1039 				libcerror_error_set(
1040 				 error,
1041 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1042 				 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1043 				 "%s: unable to append offset range to offset list.",
1044 				 function );
1045 
1046 				goto on_error;
1047 			}
1048 */
1049 		}
1050 #if defined( HAVE_DEBUG_OUTPUT )
1051 		if( libcnotify_verbose != 0 )
1052 		{
1053 			libcnotify_printf(
1054 			 "\n" );
1055 		}
1056 #endif
1057 	}
1058 	if( libfdata_vector_free(
1059 	     &cluster_block_vector,
1060 	     error ) != 1 )
1061 	{
1062 		libcerror_error_set(
1063 		 error,
1064 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1065 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1066 		 "%s: unable to free cluster block vector.",
1067 		 function );
1068 
1069 		goto on_error;
1070 	}
1071 	if( libfcache_cache_free(
1072 	     &cluster_block_cache,
1073 	     error ) != 1 )
1074 	{
1075 		libcerror_error_set(
1076 		 error,
1077 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1078 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1079 		 "%s: unable to free cluster block cache.",
1080 		 function );
1081 
1082 		goto on_error;
1083 	}
1084 	return( 1 );
1085 
1086 on_error:
1087 	if( cluster_block_cache != NULL )
1088 	{
1089 		libfcache_cache_free(
1090 		 &cluster_block_cache,
1091 		 NULL );
1092 	}
1093 	if( cluster_block_vector != NULL )
1094 	{
1095 		libfdata_vector_free(
1096 		 &cluster_block_vector,
1097 		 NULL );
1098 	}
1099 	return( -1 );
1100 }
1101 
1102 /* Reads the security descriptors
1103  * Returns 1 if successful or -1 on error
1104  */
libfsntfs_file_system_read_security_descriptors(libfsntfs_file_system_t * file_system,libfsntfs_io_handle_t * io_handle,libbfio_handle_t * file_io_handle,libcerror_error_t ** error)1105 int libfsntfs_file_system_read_security_descriptors(
1106      libfsntfs_file_system_t *file_system,
1107      libfsntfs_io_handle_t *io_handle,
1108      libbfio_handle_t *file_io_handle,
1109      libcerror_error_t **error )
1110 {
1111 	libfsntfs_file_name_values_t *file_name_values = NULL;
1112 	libfsntfs_mft_attribute_t *data_attribute      = NULL;
1113 	libfsntfs_mft_attribute_t *mft_attribute       = NULL;
1114 	libfsntfs_mft_entry_t *mft_entry               = NULL;
1115 	static char *function                          = "libfsntfs_file_system_read_security_descriptors";
1116 	int result                                     = 0;
1117 
1118 	if( file_system == NULL )
1119 	{
1120 		libcerror_error_set(
1121 		 error,
1122 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1123 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1124 		 "%s: invalid file system.",
1125 		 function );
1126 
1127 		return( -1 );
1128 	}
1129 	if( file_system->security_descriptor_index != NULL )
1130 	{
1131 		libcerror_error_set(
1132 		 error,
1133 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1134 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1135 		 "%s: invalid file system - security descriptor index value already set.",
1136 		 function );
1137 
1138 		return( -1 );
1139 	}
1140 	if( libfsntfs_mft_get_mft_entry_by_index(
1141 	     file_system->mft,
1142 	     file_io_handle,
1143 	     LIBFSNTFS_MFT_ENTRY_INDEX_SECURE,
1144 	     &mft_entry,
1145 	     error ) != 1 )
1146 	{
1147 		libcerror_error_set(
1148 		 error,
1149 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1150 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1151 		 "%s: unable to retrieve MFT entry: %d.",
1152 		 function,
1153 		 LIBFSNTFS_MFT_ENTRY_INDEX_SECURE );
1154 
1155 		goto on_error;
1156 	}
1157 	if( mft_entry == NULL )
1158 	{
1159 		libcerror_error_set(
1160 		 error,
1161 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1162 		 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1163 		 "%s: missing MFT entry: %d.",
1164 		 function,
1165 		 LIBFSNTFS_MFT_ENTRY_INDEX_SECURE );
1166 
1167 		goto on_error;
1168 	}
1169 	if( libfsntfs_mft_entry_get_attribute_by_index(
1170 	     mft_entry,
1171 	     mft_entry->file_name_attribute_index,
1172 	     &mft_attribute,
1173 	     error ) != 1 )
1174 	{
1175 		libcerror_error_set(
1176 		 error,
1177 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1178 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1179 		 "%s: unable to retrieve attribute: %d from MFT entry: %d.",
1180 		 function,
1181 		 mft_entry->file_name_attribute_index,
1182 		 LIBFSNTFS_MFT_ENTRY_INDEX_SECURE );
1183 
1184 		goto on_error;
1185 	}
1186 	if( libfsntfs_file_name_values_initialize(
1187 	     &file_name_values,
1188 	     error ) != 1 )
1189 	{
1190 		libcerror_error_set(
1191 		 error,
1192 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1193 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1194 		 "%s: unable to create file name values.",
1195 		 function );
1196 
1197 		goto on_error;
1198 	}
1199 	if( libfsntfs_file_name_values_read_from_mft_attribute(
1200 	     file_name_values,
1201 	     mft_attribute,
1202 	     error ) != 1 )
1203 	{
1204 		libcerror_error_set(
1205 		 error,
1206 		 LIBCERROR_ERROR_DOMAIN_IO,
1207 		 LIBCERROR_IO_ERROR_READ_FAILED,
1208 		 "%s: unable to read file name values from attribute: %d from MFT entry: %d.",
1209 		 function,
1210 		 mft_entry->file_name_attribute_index,
1211 		 LIBFSNTFS_MFT_ENTRY_INDEX_SECURE );
1212 
1213 		goto on_error;
1214 	}
1215 	result = libfsntfs_name_compare_with_utf8_string(
1216 	          file_name_values->name,
1217 	          file_name_values->name_size,
1218 	          (uint8_t *) "$Secure",
1219 	          7,
1220 	          1,
1221 	          error );
1222 
1223 	if( result == -1 )
1224 	{
1225 		libcerror_error_set(
1226 		 error,
1227 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1228 		 LIBCERROR_RUNTIME_ERROR_GENERIC,
1229 		 "%s: unable to compare UTF-8 string with data attribute name.",
1230 		 function );
1231 
1232 		goto on_error;
1233 	}
1234 	else if( result == LIBUNA_COMPARE_EQUAL )
1235 	{
1236 		if( libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name(
1237 		     mft_entry,
1238 		     (uint8_t *) "$SDS",
1239 		     4,
1240 		     &data_attribute,
1241 		     error ) != 1 )
1242 		{
1243 			libcerror_error_set(
1244 			 error,
1245 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1246 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1247 			 "%s: unable to retrieve $SDS data attribute.",
1248 			 function );
1249 
1250 			goto on_error;
1251 		}
1252 		if( libfsntfs_security_descriptor_index_initialize(
1253 		     &( file_system->security_descriptor_index ),
1254 		     io_handle,
1255 		     file_io_handle,
1256 		     data_attribute,
1257 		     error ) != 1 )
1258 		{
1259 			libcerror_error_set(
1260 			 error,
1261 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1262 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1263 			 "%s: unable to create security descriptor index.",
1264 			 function );
1265 
1266 			goto on_error;
1267 		}
1268 		if( libfsntfs_security_descriptor_index_read_sii_index(
1269 		     file_system->security_descriptor_index,
1270 		     io_handle,
1271 		     file_io_handle,
1272 		     mft_entry,
1273 		     error ) != 1 )
1274 		{
1275 			libcerror_error_set(
1276 			 error,
1277 			 LIBCERROR_ERROR_DOMAIN_IO,
1278 			 LIBCERROR_IO_ERROR_READ_FAILED,
1279 			 "%s: unable to read security descriptor identifier ($SII) index.",
1280 			 function );
1281 
1282 			goto on_error;
1283 		}
1284 	}
1285 	if( libfsntfs_file_name_values_free(
1286 	     &file_name_values,
1287 	     error ) != 1 )
1288 	{
1289 		libcerror_error_set(
1290 		 error,
1291 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1292 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1293 		 "%s: unable to free file name values.",
1294 		 function );
1295 
1296 		goto on_error;
1297 	}
1298 	return( 1 );
1299 
1300 on_error:
1301 	if( file_system->security_descriptor_index != NULL )
1302 	{
1303 		libfsntfs_security_descriptor_index_free(
1304 		 &( file_system->security_descriptor_index ),
1305 		 NULL );
1306 	}
1307 	if( file_name_values != NULL )
1308 	{
1309 		libfsntfs_file_name_values_free(
1310 		 &file_name_values,
1311 		 NULL );
1312 	}
1313 	return( -1 );
1314 }
1315 
1316 /* Retrieves the number of MFT entries
1317  * Returns 1 if successful or -1 on error
1318  */
libfsntfs_file_system_get_number_of_mft_entries(libfsntfs_file_system_t * file_system,uint64_t * number_of_mft_entries,libcerror_error_t ** error)1319 int libfsntfs_file_system_get_number_of_mft_entries(
1320      libfsntfs_file_system_t *file_system,
1321      uint64_t *number_of_mft_entries,
1322      libcerror_error_t **error )
1323 {
1324 	static char *function = "libfsntfs_file_system_get_number_of_mft_entries";
1325 
1326 	if( file_system == NULL )
1327 	{
1328 		libcerror_error_set(
1329 		 error,
1330 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1331 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1332 		 "%s: invalid file system.",
1333 		 function );
1334 
1335 		return( -1 );
1336 	}
1337 	if( libfsntfs_mft_get_number_of_entries(
1338 	     file_system->mft,
1339 	     number_of_mft_entries,
1340 	     error ) != 1 )
1341 	{
1342 		libcerror_error_set(
1343 		 error,
1344 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1345 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1346 		 "%s: unable to retrieve number of MFT entries.",
1347 		 function );
1348 
1349 		return( -1 );
1350 	}
1351 	return( 1 );
1352 }
1353 
1354 /* Retrieves the MFT entry for a specific index
1355  * Returns 1 if successful or -1 on error
1356  */
libfsntfs_file_system_get_mft_entry_by_index(libfsntfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint64_t mft_entry_index,libfsntfs_mft_entry_t ** mft_entry,libcerror_error_t ** error)1357 int libfsntfs_file_system_get_mft_entry_by_index(
1358      libfsntfs_file_system_t *file_system,
1359      libbfio_handle_t *file_io_handle,
1360      uint64_t mft_entry_index,
1361      libfsntfs_mft_entry_t **mft_entry,
1362      libcerror_error_t **error )
1363 {
1364 	static char *function = "libfsntfs_file_system_get_mft_entry_by_index";
1365 
1366 	if( file_system == NULL )
1367 	{
1368 		libcerror_error_set(
1369 		 error,
1370 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1371 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1372 		 "%s: invalid file system.",
1373 		 function );
1374 
1375 		return( -1 );
1376 	}
1377 	if( libfsntfs_mft_get_mft_entry_by_index(
1378 	     file_system->mft,
1379 	     file_io_handle,
1380 	     mft_entry_index,
1381 	     mft_entry,
1382 	     error ) != 1 )
1383 	{
1384 		libcerror_error_set(
1385 		 error,
1386 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1387 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1388 		 "%s: unable to retrieve MFT entry: %" PRIi64 ".",
1389 		 function,
1390 		 mft_entry_index );
1391 
1392 		return( -1 );
1393 	}
1394 	return( 1 );
1395 }
1396 
1397 /* Retrieves the MFT entry for a specific index
1398  * This function creates new MFT entry
1399  * Returns 1 if successful or -1 on error
1400  */
libfsntfs_file_system_get_mft_entry_by_index_no_cache(libfsntfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint64_t mft_entry_index,libfsntfs_mft_entry_t ** mft_entry,libcerror_error_t ** error)1401 int libfsntfs_file_system_get_mft_entry_by_index_no_cache(
1402      libfsntfs_file_system_t *file_system,
1403      libbfio_handle_t *file_io_handle,
1404      uint64_t mft_entry_index,
1405      libfsntfs_mft_entry_t **mft_entry,
1406      libcerror_error_t **error )
1407 {
1408 	static char *function = "libfsntfs_file_system_get_mft_entry_by_index_no_cache";
1409 
1410 	if( file_system == NULL )
1411 	{
1412 		libcerror_error_set(
1413 		 error,
1414 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1415 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1416 		 "%s: invalid file system.",
1417 		 function );
1418 
1419 		return( -1 );
1420 	}
1421 	if( libfsntfs_mft_get_mft_entry_by_index_no_cache(
1422 	     file_system->mft,
1423 	     file_io_handle,
1424 	     mft_entry_index,
1425 	     mft_entry,
1426 	     error ) != 1 )
1427 	{
1428 		libcerror_error_set(
1429 		 error,
1430 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1431 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1432 		 "%s: unable to retrieve MFT entry: %" PRIi64 ".",
1433 		 function,
1434 		 mft_entry_index );
1435 
1436 		return( -1 );
1437 	}
1438 	return( 1 );
1439 }
1440 
1441 /* Retrieves the security descriptor for a specific identifier
1442  * This function creates new security descriptor values
1443  * Returns 1 if successful, 0 if not available or -1 on error
1444  */
libfsntfs_file_system_get_security_descriptor_values_by_identifier(libfsntfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint32_t security_descriptor_identifier,libfsntfs_security_descriptor_values_t ** security_descriptor_values,libcerror_error_t ** error)1445 int libfsntfs_file_system_get_security_descriptor_values_by_identifier(
1446      libfsntfs_file_system_t *file_system,
1447      libbfio_handle_t *file_io_handle,
1448      uint32_t security_descriptor_identifier,
1449      libfsntfs_security_descriptor_values_t **security_descriptor_values,
1450      libcerror_error_t **error )
1451 {
1452 	static char *function = "libfsntfs_file_system_get_security_descriptor_values_by_identifier";
1453 	int result            = 0;
1454 
1455 	if( file_system == NULL )
1456 	{
1457 		libcerror_error_set(
1458 		 error,
1459 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1460 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1461 		 "%s: invalid file system.",
1462 		 function );
1463 
1464 		return( -1 );
1465 	}
1466 	if( file_system->security_descriptor_index != NULL )
1467 	{
1468 		result = libfsntfs_security_descriptor_index_get_entry_by_identifier(
1469 		          file_system->security_descriptor_index,
1470 		          file_io_handle,
1471 		          security_descriptor_identifier,
1472 		          security_descriptor_values,
1473 		          error );
1474 
1475 		if( result == -1 )
1476 		{
1477 			libcerror_error_set(
1478 			 error,
1479 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1480 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1481 			 "%s: unable to retrieve security descriptor from index for identifier: %" PRIu32 ".",
1482 			 function,
1483 			 security_descriptor_identifier );
1484 
1485 			return( -1 );
1486 		}
1487 	}
1488 	return( result );
1489 }
1490 
1491 /* Retrieves the path hint of a specific file reference
1492  * Returns 1 if successful, 0 if not available or -1 on error
1493  */
libfsntfs_file_system_get_path_hint(libfsntfs_file_system_t * file_system,libbfio_handle_t * file_io_handle,uint64_t file_reference,libfsntfs_path_hint_t ** path_hint,int recursion_depth,libcerror_error_t ** error)1494 int libfsntfs_file_system_get_path_hint(
1495      libfsntfs_file_system_t *file_system,
1496      libbfio_handle_t *file_io_handle,
1497      uint64_t file_reference,
1498      libfsntfs_path_hint_t **path_hint,
1499      int recursion_depth,
1500      libcerror_error_t **error )
1501 {
1502 	libcdata_tree_node_t *upper_node               = NULL;
1503 	libfsntfs_file_name_values_t *file_name_values = NULL;
1504 	libfsntfs_mft_attribute_t *mft_attribute       = NULL;
1505 	libfsntfs_mft_entry_t *mft_entry               = NULL;
1506 	libfsntfs_path_hint_t *existing_path_hint      = NULL;
1507 	libfsntfs_path_hint_t *lookup_path_hint        = NULL;
1508 	libfsntfs_path_hint_t *parent_path_hint        = NULL;
1509 	libfsntfs_path_hint_t *safe_path_hint          = NULL;
1510 	uint8_t *parent_path                           = NULL;
1511 	static char *function                          = "libfsntfs_file_system_get_path_hint";
1512 	size_t name_size                               = 0;
1513 	size_t parent_path_size                        = 0;
1514 	uint64_t mft_entry_index                       = 0;
1515 	uint64_t mft_entry_file_reference              = 0;
1516 	uint64_t parent_file_reference                 = 0;
1517 	uint64_t parent_mft_entry_index                = 0;
1518 	uint32_t attribute_type                        = 0;
1519 	uint16_t mft_entry_sequence_number             = 0;
1520 	uint16_t sequence_number                       = 0;
1521 	int attribute_index                            = 0;
1522 	int number_of_attributes                       = 0;
1523 	int result                                     = 0;
1524 	int value_index                                = 0;
1525 
1526 	if( file_system == NULL )
1527 	{
1528 		libcerror_error_set(
1529 		 error,
1530 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1531 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1532 		 "%s: invalid file system.",
1533 		 function );
1534 
1535 		return( -1 );
1536 	}
1537 	if( path_hint == NULL )
1538 	{
1539 		libcerror_error_set(
1540 		 error,
1541 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1542 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1543 		 "%s: invalid path hint.",
1544 		 function );
1545 
1546 		return( -1 );
1547 	}
1548 	if( ( recursion_depth < 0 )
1549 	 || ( recursion_depth > LIBFSNTFS_MAXIMUM_RECURSION_DEPTH ) )
1550 	{
1551 		libcerror_error_set(
1552 		 error,
1553 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1554 		 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1555 		 "%s: invalid recursion depth value out of bounds.",
1556 		 function );
1557 
1558 		return( -1 );
1559 	}
1560 	mft_entry_index = file_reference & 0xffffffffffffUL;
1561 
1562 	if( libfsntfs_file_system_get_mft_entry_by_index(
1563 	     file_system,
1564 	     file_io_handle,
1565 	     mft_entry_index,
1566 	     &mft_entry,
1567 	     error ) != 1 )
1568 	{
1569 		libcerror_error_set(
1570 		 error,
1571 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1572 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1573 		 "%s: unable to retrieve MFT entry: %" PRIu64 ".",
1574 		 function,
1575 		 mft_entry_index );
1576 
1577 		goto on_error;
1578 	}
1579 	if( libfsntfs_mft_entry_get_file_reference(
1580 	     mft_entry,
1581 	     &mft_entry_file_reference,
1582 	     error ) != 1 )
1583 	{
1584 		libcerror_error_set(
1585 		 error,
1586 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1587 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1588 		 "%s: unable to retrieve MFT entry: %" PRIu64 ".",
1589 		 function,
1590 		 mft_entry_index );
1591 
1592 		goto on_error;
1593 	}
1594 	if( mft_entry_file_reference != file_reference )
1595 	{
1596 		result = libfsntfs_mft_entry_is_allocated(
1597 		          mft_entry,
1598 		          error );
1599 
1600 		if( result == -1 )
1601 		{
1602 			libcerror_error_set(
1603 			 error,
1604 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1605 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1606 			 "%s: unable to retrieve MFT entry: %" PRIu64 ".",
1607 			 function,
1608 			 mft_entry_index );
1609 
1610 			goto on_error;
1611 		}
1612 		else if( result != 0 )
1613 		{
1614 			return( 0 );
1615 		}
1616 		/* The sequence number is updated when the MFT entry is deleted
1617 		 */
1618 		sequence_number           = (uint16_t) ( file_reference >> 48 );
1619 		mft_entry_sequence_number = (uint16_t) ( mft_entry_file_reference >> 48 );
1620 
1621 		if( sequence_number != ( mft_entry_sequence_number - 1 ) )
1622 		{
1623 			return( 0 );
1624 		}
1625 	}
1626 	if( libfsntfs_path_hint_initialize(
1627 	     &lookup_path_hint,
1628 	     error ) != 1 )
1629 	{
1630 		libcerror_error_set(
1631 		 error,
1632 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1633 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1634 		 "%s: unable to create path hint.",
1635 		 function );
1636 
1637 		goto on_error;
1638 	}
1639 	lookup_path_hint->file_reference = mft_entry_file_reference;
1640 
1641 	result = libcdata_btree_get_value_by_value(
1642 	          file_system->path_hints_tree,
1643 	          (intptr_t *) lookup_path_hint,
1644 	          (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference,
1645 	          &upper_node,
1646 	          (intptr_t **) path_hint,
1647 	          error );
1648 
1649 	if( result == -1 )
1650 	{
1651 		libcerror_error_set(
1652 		 error,
1653 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1654 		 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1655 		 "%s: unable to retrieve path hint from tree.",
1656 		 function );
1657 
1658 		goto on_error;
1659 	}
1660 	else if( result == 0 )
1661 	{
1662 		if( libfsntfs_mft_entry_get_number_of_attributes(
1663 		     mft_entry,
1664 		     &number_of_attributes,
1665 		     error ) != 1 )
1666 		{
1667 			libcerror_error_set(
1668 			 error,
1669 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1670 			 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1671 			 "%s: unable to retrieve number of attributes.",
1672 			 function );
1673 
1674 			goto on_error;
1675 		}
1676 		for( attribute_index = 0;
1677 		     attribute_index < number_of_attributes;
1678 		     attribute_index++ )
1679 		{
1680 			if( libfsntfs_mft_entry_get_attribute_by_index(
1681 			     mft_entry,
1682 			     attribute_index,
1683 			     &mft_attribute,
1684 			     error ) != 1 )
1685 			{
1686 				libcerror_error_set(
1687 				 error,
1688 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1689 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1690 				 "%s: unable to retrieve attribute: %d.",
1691 				 function,
1692 				 attribute_index );
1693 
1694 				goto on_error;
1695 			}
1696 			if( libfsntfs_mft_attribute_get_type(
1697 			     mft_attribute,
1698 			     &attribute_type,
1699 			     error ) != 1 )
1700 			{
1701 				libcerror_error_set(
1702 				 error,
1703 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1704 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1705 				 "%s: unable to retrieve attribute: %d type.",
1706 				 function,
1707 				 attribute_index );
1708 
1709 				goto on_error;
1710 			}
1711 			if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME )
1712 			{
1713 				continue;
1714 			}
1715 			if( libfsntfs_file_name_values_initialize(
1716 			     &file_name_values,
1717 			     error ) != 1 )
1718 			{
1719 				libcerror_error_set(
1720 				 error,
1721 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1722 				 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1723 				 "%s: unable to create file name values.",
1724 				 function );
1725 
1726 				goto on_error;
1727 			}
1728 			if( libfsntfs_file_name_values_read_from_mft_attribute(
1729 			     file_name_values,
1730 			     mft_attribute,
1731 			     error ) != 1 )
1732 			{
1733 				libcerror_error_set(
1734 				 error,
1735 				 LIBCERROR_ERROR_DOMAIN_IO,
1736 				 LIBCERROR_IO_ERROR_READ_FAILED,
1737 				 "%s: unable to read file name values.",
1738 				 function );
1739 
1740 				goto on_error;
1741 			}
1742 			if( libfsntfs_file_name_values_get_parent_file_reference(
1743 			     file_name_values,
1744 			     &parent_file_reference,
1745 			     error ) != 1 )
1746 			{
1747 				libcerror_error_set(
1748 				 error,
1749 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1750 				 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1751 				 "%s: unable to retrieve parent file reference.",
1752 				 function );
1753 
1754 				goto on_error;
1755 			}
1756 			parent_mft_entry_index = parent_file_reference & 0xffffffffffffUL;
1757 
1758 			if( file_name_values->name_space != LIBFSNTFS_FILE_NAME_SPACE_DOS )
1759 			{
1760 				parent_path      = NULL;
1761 				parent_path_size = 0;
1762 
1763 				if( ( mft_entry_index != LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY )
1764 				 && ( parent_mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY ) )
1765 				{
1766 					parent_path      = (uint8_t *) "";
1767 					parent_path_size = 1;
1768 				}
1769 				else if( ( parent_mft_entry_index != 0 )
1770 				      && ( parent_mft_entry_index != mft_entry_index ) )
1771 				{
1772 					result = libfsntfs_file_system_get_path_hint(
1773 					          file_system,
1774 					          file_io_handle,
1775 					          parent_file_reference,
1776 					          &parent_path_hint,
1777 					          recursion_depth + 1,
1778 					          error );
1779 
1780 					if( result == -1 )
1781 					{
1782 						libcerror_error_set(
1783 						 error,
1784 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1785 						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1786 						 "%s: unable to retrieve path hint for MFT entry: %" PRIu64 ".",
1787 						 function,
1788 						 parent_mft_entry_index );
1789 
1790 						goto on_error;
1791 					}
1792 					else if( result == 0 )
1793 					{
1794 						parent_path      = (uint8_t *) "$Orphan";
1795 						parent_path_size = 8;
1796 					}
1797 					else
1798 					{
1799 						parent_path      = parent_path_hint->path;
1800 						parent_path_size = parent_path_hint->path_size;
1801 					}
1802 				}
1803 				if( libfsntfs_file_name_values_get_utf8_name_size(
1804 				     file_name_values,
1805 				     &name_size,
1806 				     error ) != 1 )
1807 				{
1808 					libcerror_error_set(
1809 					 error,
1810 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1811 					 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1812 					 "%s: unable to retrieve size of UTF-8 name.",
1813 					 function );
1814 
1815 					goto on_error;
1816 				}
1817 				if( libfsntfs_path_hint_initialize(
1818 				     &safe_path_hint,
1819 				     error ) != 1 )
1820 				{
1821 					libcerror_error_set(
1822 					 error,
1823 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1824 					 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1825 					 "%s: unable to create path hint.",
1826 					 function );
1827 
1828 					goto on_error;
1829 				}
1830 				safe_path_hint->file_reference = file_reference;
1831 				safe_path_hint->path_size      = parent_path_size + name_size;
1832 
1833 				safe_path_hint->path = (uint8_t *) memory_allocate(
1834 								    sizeof( uint8_t ) * safe_path_hint->path_size );
1835 
1836 				if( safe_path_hint->path == NULL )
1837 				{
1838 					libcerror_error_set(
1839 					 error,
1840 					 LIBCERROR_ERROR_DOMAIN_MEMORY,
1841 					 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1842 					 "%s: unable to create path.",
1843 					 function );
1844 
1845 					goto on_error;
1846 				}
1847 				if( ( parent_path != NULL )
1848 				 && ( parent_path_size > 0 ) )
1849 				{
1850 					if( memory_copy(
1851 					     safe_path_hint->path,
1852 					     parent_path,
1853 					     parent_path_size ) == NULL )
1854 					{
1855 						libcerror_error_set(
1856 						 error,
1857 						 LIBCERROR_ERROR_DOMAIN_MEMORY,
1858 						 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1859 						 "%s: unable to copy parent path to path.",
1860 						 function );
1861 
1862 						goto on_error;
1863 					}
1864 					safe_path_hint->path[ parent_path_size - 1 ] = '\\';
1865 				}
1866 				if( name_size > 0 )
1867 				{
1868 					if( libfsntfs_file_name_values_get_utf8_name(
1869 					     file_name_values,
1870 					     &( safe_path_hint->path[ parent_path_size ] ),
1871 					     name_size,
1872 					     error ) != 1 )
1873 					{
1874 						libcerror_error_set(
1875 						 error,
1876 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1877 						 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1878 						 "%s: unable to retrieve UTF-8 name.",
1879 						 function );
1880 
1881 						goto on_error;
1882 					}
1883 				}
1884 				if( mft_entry_index == LIBFSNTFS_MFT_ENTRY_INDEX_ROOT_DIRECTORY )
1885 				{
1886 					safe_path_hint->path[ 0 ] = '\\';
1887 				}
1888 				result = libcdata_btree_insert_value(
1889 					  file_system->path_hints_tree,
1890 					  &value_index,
1891 					  (intptr_t *) safe_path_hint,
1892 					  (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_path_hint_compare_by_file_reference,
1893 					  &upper_node,
1894 					  (intptr_t **) &existing_path_hint,
1895 					  error );
1896 
1897 				if( result == -1 )
1898 				{
1899 					libcerror_error_set(
1900 					 error,
1901 					 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1902 					 LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1903 					 "%s: unable to insert path hint into tree.",
1904 					 function );
1905 
1906 					goto on_error;
1907 				}
1908 				else if( result == 0 )
1909 				{
1910 					if( libfsntfs_path_hint_free(
1911 					     &safe_path_hint,
1912 					     error ) != 1 )
1913 					{
1914 						libcerror_error_set(
1915 						 error,
1916 						 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1917 						 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1918 						 "%s: unable to free path hint.",
1919 						 function );
1920 
1921 						goto on_error;
1922 					}
1923 					*path_hint = existing_path_hint;
1924 				}
1925 				else
1926 				{
1927 					*path_hint = safe_path_hint;
1928 
1929 					safe_path_hint = NULL;
1930 				}
1931 				result = 1;
1932 			}
1933 			if( libfsntfs_file_name_values_free(
1934 			     &file_name_values,
1935 			     error ) != 1 )
1936 			{
1937 				libcerror_error_set(
1938 				 error,
1939 				 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1940 				 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1941 				 "%s: unable to free file name values.",
1942 				 function );
1943 
1944 				goto on_error;
1945 			}
1946 		}
1947 	}
1948 	if( libfsntfs_path_hint_free(
1949 	     &lookup_path_hint,
1950 	     error ) != 1 )
1951 	{
1952 		libcerror_error_set(
1953 		 error,
1954 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1955 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1956 		 "%s: unable to free path hint.",
1957 		 function );
1958 
1959 		goto on_error;
1960 	}
1961 	return( result );
1962 
1963 on_error:
1964 	if( safe_path_hint != NULL )
1965 	{
1966 		libfsntfs_path_hint_free(
1967 		 &safe_path_hint,
1968 		 NULL );
1969 	}
1970 	if( file_name_values != NULL )
1971 	{
1972 		libfsntfs_file_name_values_free(
1973 		 &file_name_values,
1974 		 NULL );
1975 	}
1976 	if( lookup_path_hint != NULL )
1977 	{
1978 		libfsntfs_path_hint_free(
1979 		 &lookup_path_hint,
1980 		 NULL );
1981 	}
1982 	return( -1 );
1983 }
1984 
1985