Coverage Report

Created: 2025-06-24 07:14

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