Coverage Report

Created: 2024-02-25 07:20

/src/libfsntfs/libfsntfs/libfsntfs_mft.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * MFT 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 <memory.h>
24
#include <types.h>
25
26
#include "libfsntfs_definitions.h"
27
#include "libfsntfs_io_handle.h"
28
#include "libfsntfs_libbfio.h"
29
#include "libfsntfs_libcerror.h"
30
#include "libfsntfs_libfcache.h"
31
#include "libfsntfs_libfdata.h"
32
#include "libfsntfs_mft.h"
33
#include "libfsntfs_mft_attribute_list.h"
34
#include "libfsntfs_mft_entry.h"
35
#include "libfsntfs_types.h"
36
37
/* Creates a MFT
38
 * Make sure the value mft is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsntfs_mft_initialize(
42
     libfsntfs_mft_t **mft,
43
     libfsntfs_io_handle_t *io_handle,
44
     size64_t mft_entry_size,
45
     uint8_t flags,
46
     libcerror_error_t **error )
47
7.66k
{
48
7.66k
  static char *function = "libfsntfs_mft_initialize";
49
50
7.66k
  if( mft == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid MFT.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
7.66k
  if( *mft != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid MFT value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
7.66k
  if( io_handle == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
78
0
     "%s: invalid IO handle.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
7.66k
  *mft = memory_allocate_structure(
84
7.66k
          libfsntfs_mft_t );
85
86
7.66k
  if( *mft == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
92
0
     "%s: unable to create MFT.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
7.66k
  if( memory_set(
98
7.66k
       *mft,
99
7.66k
       0,
100
7.66k
       sizeof( libfsntfs_mft_t ) ) == NULL )
101
0
  {
102
0
    libcerror_error_set(
103
0
     error,
104
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
105
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
106
0
     "%s: unable to clear MFT.",
107
0
     function );
108
109
0
    memory_free(
110
0
     *mft );
111
112
0
    *mft = NULL;
113
114
0
    return( -1 );
115
0
  }
116
7.66k
  if( libfdata_vector_initialize(
117
7.66k
       &( ( *mft )->mft_entry_vector ),
118
7.66k
       mft_entry_size,
119
7.66k
       (intptr_t *) io_handle,
120
7.66k
       NULL,
121
7.66k
       NULL,
122
7.66k
       (int (*)(intptr_t *, intptr_t *, libfdata_vector_t *, libfdata_cache_t *, int, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libfsntfs_mft_entry_read_element_data,
123
7.66k
       NULL,
124
7.66k
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
125
7.66k
       error ) != 1 )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
130
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
131
0
     "%s: unable to create MFT entry vector.",
132
0
     function );
133
134
0
    goto on_error;
135
0
  }
136
7.66k
  if( libfcache_cache_initialize(
137
7.66k
       &( ( *mft )->mft_entry_cache ),
138
7.66k
       LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_MFT_ENTRIES,
139
7.66k
       error ) != 1 )
140
0
  {
141
0
    libcerror_error_set(
142
0
     error,
143
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
144
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
145
0
     "%s: unable to create MFT entry cache.",
146
0
     function );
147
148
0
    goto on_error;
149
0
  }
150
7.66k
  if( libfcache_cache_initialize(
151
7.66k
       &( ( *mft )->single_mft_entry_cache ),
152
7.66k
       1,
153
7.66k
       error ) != 1 )
154
0
  {
155
0
    libcerror_error_set(
156
0
     error,
157
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
158
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
159
0
     "%s: unable to create signle MFT entry cache.",
160
0
     function );
161
162
0
    goto on_error;
163
0
  }
164
7.66k
  ( *mft )->io_handle = io_handle;
165
7.66k
  ( *mft )->flags     = flags;
166
167
7.66k
  return( 1 );
168
169
0
on_error:
170
0
  if( *mft != NULL )
171
0
  {
172
0
    if( ( *mft )->mft_entry_cache != NULL )
173
0
    {
174
0
      libfcache_cache_free(
175
0
       &( ( *mft )->mft_entry_cache ),
176
0
       NULL );
177
0
    }
178
0
    if( ( *mft )->mft_entry_vector != NULL )
179
0
    {
180
0
      libfdata_vector_free(
181
0
       &( ( *mft )->mft_entry_vector ),
182
0
       NULL );
183
0
    }
184
0
    memory_free(
185
0
     *mft );
186
187
0
    *mft = NULL;
188
0
  }
189
0
  return( -1 );
190
7.66k
}
191
192
/* Frees a MFT
193
 * Returns 1 if successful or -1 on error
194
 */
195
int libfsntfs_mft_free(
196
     libfsntfs_mft_t **mft,
197
     libcerror_error_t **error )
198
7.66k
{
199
7.66k
  static char *function = "libfsntfs_mft_free";
200
7.66k
  int result            = 1;
201
202
7.66k
  if( mft == NULL )
203
0
  {
204
0
    libcerror_error_set(
205
0
     error,
206
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
208
0
     "%s: invalid MFT.",
209
0
     function );
210
211
0
    return( -1 );
212
0
  }
213
7.66k
  if( *mft != NULL )
214
7.66k
  {
215
7.66k
    if( libfdata_vector_free(
216
7.66k
         &( ( *mft )->mft_entry_vector ),
217
7.66k
         error ) != 1 )
218
0
    {
219
0
      libcerror_error_set(
220
0
       error,
221
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
223
0
       "%s: unable to free MFT entry vector.",
224
0
       function );
225
226
0
      result = -1;
227
0
    }
228
7.66k
    if( libfcache_cache_free(
229
7.66k
         &( ( *mft )->mft_entry_cache ),
230
7.66k
         error ) != 1 )
231
0
    {
232
0
      libcerror_error_set(
233
0
       error,
234
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
235
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
236
0
       "%s: unable to free MFT entry cache.",
237
0
       function );
238
239
0
      result = -1;
240
0
    }
241
7.66k
    if( libfcache_cache_free(
242
7.66k
         &( ( *mft )->single_mft_entry_cache ),
243
7.66k
         error ) != 1 )
244
0
    {
245
0
      libcerror_error_set(
246
0
       error,
247
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
248
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
249
0
       "%s: unable to free single MFT entry cache.",
250
0
       function );
251
252
0
      result = -1;
253
0
    }
254
7.66k
    if( ( *mft )->attribute_list_tree != NULL )
255
365
    {
256
365
      if( libcdata_btree_free(
257
365
           &( ( *mft )->attribute_list_tree ),
258
365
           (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free,
259
365
           error ) != 1 )
260
0
      {
261
0
        libcerror_error_set(
262
0
         error,
263
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
264
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
265
0
         "%s: unable to free attribute list tree.",
266
0
         function );
267
268
0
        result = -1;
269
0
      }
270
365
    }
271
7.66k
    memory_free(
272
7.66k
     *mft );
273
274
7.66k
    *mft = NULL;
275
7.66k
  }
276
7.66k
  return( result );
277
7.66k
}
278
279
/* Reads the attribute list data MFT entries
280
 * Returns 1 if successful or -1 on error
281
 */
282
int libfsntfs_mft_read_list_data_mft_entries(
283
     libfsntfs_mft_t *mft,
284
     libbfio_handle_t *file_io_handle,
285
     libcerror_error_t **error )
286
369
{
287
369
  libcdata_tree_node_t *upper_node                        = NULL;
288
369
  libfsntfs_mft_attribute_list_t *attribute_list          = NULL;
289
369
  libfsntfs_mft_attribute_list_t *existing_attribute_list = NULL;
290
369
  libfsntfs_mft_entry_t *mft_entry                        = NULL;
291
369
  static char *function                                   = "libfsntfs_mft_read_list_data_mft_entries";
292
369
  uint64_t base_record_file_reference                     = 0;
293
369
  uint64_t file_reference                                 = 0;
294
369
  uint64_t mft_entry_index                                = 0;
295
369
  int result                                              = 0;
296
369
  int value_index                                         = 0;
297
298
369
  if( mft == NULL )
299
0
  {
300
0
    libcerror_error_set(
301
0
     error,
302
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
303
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
304
0
     "%s: invalid MFT.",
305
0
     function );
306
307
0
    return( -1 );
308
0
  }
309
369
  if( mft->attribute_list_tree != NULL )
310
0
  {
311
0
    libcerror_error_set(
312
0
     error,
313
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
314
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
315
0
     "%s: invalid MFT - attribute list tree value already set.",
316
0
     function );
317
318
0
    return( -1 );
319
0
  }
320
369
  if( libcdata_btree_initialize(
321
369
       &( mft->attribute_list_tree ),
322
369
       LIBFSNTFS_INDEX_TREE_MAXIMUM_NUMBER_OF_SUB_NODES,
323
369
       error ) != 1 )
324
0
  {
325
0
    libcerror_error_set(
326
0
     error,
327
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
328
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
329
0
     "%s: unable to create attribute list B-tree.",
330
0
     function );
331
332
0
    goto on_error;
333
0
  }
334
369
  for( mft_entry_index = 0;
335
22.5k
       mft_entry_index < mft->number_of_mft_entries;
336
22.1k
       mft_entry_index++ )
337
22.1k
  {
338
22.1k
    if( libfdata_vector_get_element_value_by_index(
339
22.1k
         mft->mft_entry_vector,
340
22.1k
         (intptr_t *) file_io_handle,
341
22.1k
         (libfdata_cache_t *) mft->mft_entry_cache,
342
22.1k
         (int) mft_entry_index,
343
22.1k
         (intptr_t **) &mft_entry,
344
22.1k
         0,
345
22.1k
         error ) != 1 )
346
4
    {
347
4
      libcerror_error_set(
348
4
       error,
349
4
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
350
4
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
351
4
       "%s: unable to retrieve MFT entry: %" PRIu64 ".",
352
4
       function,
353
4
       mft_entry_index );
354
355
4
      goto on_error;
356
4
    }
357
22.1k
    result = libfsntfs_mft_entry_get_base_record_file_reference(
358
22.1k
              mft_entry,
359
22.1k
              &base_record_file_reference,
360
22.1k
              error );
361
362
22.1k
    if( result == -1 )
363
0
    {
364
0
      libcerror_error_set(
365
0
       error,
366
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
367
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
368
0
       "%s: unable to retrieve base record file reference from MFT entry: %" PRIu64 ".",
369
0
       function,
370
0
       mft_entry_index );
371
372
0
      goto on_error;
373
0
    }
374
22.1k
    if( ( result == 0 )
375
22.1k
     || ( base_record_file_reference == 0 ) )
376
15.1k
    {
377
15.1k
      continue;
378
15.1k
    }
379
6.96k
    if( libfsntfs_mft_attribute_list_initialize(
380
6.96k
         &attribute_list,
381
6.96k
         base_record_file_reference,
382
6.96k
         error ) != 1 )
383
0
    {
384
0
      libcerror_error_set(
385
0
       error,
386
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
387
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
388
0
       "%s: unable to create attribute list.",
389
0
       function );
390
391
0
      goto on_error;
392
0
    }
393
6.96k
    result = libcdata_btree_insert_value(
394
6.96k
        mft->attribute_list_tree,
395
6.96k
        &value_index,
396
6.96k
        (intptr_t *) attribute_list,
397
6.96k
        (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference,
398
6.96k
        &upper_node,
399
6.96k
        (intptr_t **) &existing_attribute_list,
400
6.96k
        error );
401
402
6.96k
    if( result == -1 )
403
0
    {
404
0
      libcerror_error_set(
405
0
       error,
406
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
407
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
408
0
       "%s: unable to insert attribute list into tree.",
409
0
       function );
410
411
0
      goto on_error;
412
0
    }
413
6.96k
    else if( result == 0 )
414
5.18k
    {
415
5.18k
      if( libfsntfs_mft_attribute_list_free(
416
5.18k
           &attribute_list,
417
5.18k
           error ) != 1 )
418
0
      {
419
0
        libcerror_error_set(
420
0
         error,
421
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
422
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
423
0
         "%s: unable to free attribute list.",
424
0
         function );
425
426
0
        goto on_error;
427
0
      }
428
5.18k
    }
429
1.77k
    else
430
1.77k
    {
431
1.77k
      existing_attribute_list = attribute_list;
432
433
1.77k
      attribute_list = NULL;
434
1.77k
    }
435
6.96k
    if( libfsntfs_mft_entry_get_file_reference(
436
6.96k
         mft_entry,
437
6.96k
         &file_reference,
438
6.96k
         error ) != 1 )
439
0
    {
440
0
      libcerror_error_set(
441
0
       error,
442
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
443
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
444
0
       "%s: unable to retrieve file reference from MFT entry: %" PRIu64 ".",
445
0
       function,
446
0
       mft_entry_index );
447
448
0
      goto on_error;
449
0
    }
450
6.96k
    if( libfsntfs_mft_attribute_list_insert_file_reference(
451
6.96k
         existing_attribute_list,
452
6.96k
         file_reference,
453
6.96k
         error ) == -1 )
454
0
    {
455
0
      libcerror_error_set(
456
0
       error,
457
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
458
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
459
0
       "%s: unable to insert attribute list data file reference in attribute list.",
460
0
       function );
461
462
0
      goto on_error;
463
0
    }
464
6.96k
  }
465
365
  return( 1 );
466
467
4
on_error:
468
4
  if( attribute_list != NULL )
469
0
  {
470
0
    libfsntfs_mft_attribute_list_free(
471
0
     &attribute_list,
472
0
     NULL );
473
0
  }
474
4
  if( mft->attribute_list_tree != NULL )
475
4
  {
476
4
    libcdata_btree_free(
477
4
     &( mft->attribute_list_tree ),
478
4
     (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_list_free,
479
4
     NULL );
480
4
  }
481
4
  return( -1 );
482
369
}
483
484
/* Retrieves the number of MFT entries
485
 * Returns 1 if successful or -1 on error
486
 */
487
int libfsntfs_mft_get_number_of_entries(
488
     libfsntfs_mft_t *mft,
489
     uint64_t *number_of_entries,
490
     libcerror_error_t **error )
491
0
{
492
0
  static char *function = "libfsntfs_mft_get_number_of_entries";
493
494
0
  if( mft == NULL )
495
0
  {
496
0
    libcerror_error_set(
497
0
     error,
498
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
499
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
500
0
     "%s: invalid MFT.",
501
0
     function );
502
503
0
    return( -1 );
504
0
  }
505
0
  if( number_of_entries == NULL )
506
0
  {
507
0
    libcerror_error_set(
508
0
     error,
509
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
510
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
511
0
     "%s: invalid number of entries.",
512
0
     function );
513
514
0
    return( -1 );
515
0
  }
516
0
  *number_of_entries = mft->number_of_mft_entries;
517
518
0
  return( 1 );
519
0
}
520
521
/* Retrieves the MFT entry for a specific index
522
 * Returns 1 if successful or -1 on error
523
 */
524
int libfsntfs_mft_get_mft_entry_by_index(
525
     libfsntfs_mft_t *mft,
526
     libbfio_handle_t *file_io_handle,
527
     uint64_t mft_entry_index,
528
     libfsntfs_mft_entry_t **mft_entry,
529
     libcerror_error_t **error )
530
3.67k
{
531
3.67k
  libfsntfs_mft_entry_t *safe_mft_entry = NULL;
532
3.67k
  static char *function                 = "libfsntfs_mft_get_mft_entry_by_index";
533
534
3.67k
  if( mft == NULL )
535
0
  {
536
0
    libcerror_error_set(
537
0
     error,
538
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
539
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
540
0
     "%s: invalid MFT.",
541
0
     function );
542
543
0
    return( -1 );
544
0
  }
545
3.67k
  if( mft_entry_index > mft->number_of_mft_entries )
546
47
  {
547
47
    libcerror_error_set(
548
47
     error,
549
47
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
550
47
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
551
47
     "%s: invalid MFT entry index value out of bounds.",
552
47
     function );
553
554
47
    return( -1 );
555
47
  }
556
3.62k
  if( mft_entry == NULL )
557
0
  {
558
0
    libcerror_error_set(
559
0
     error,
560
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
561
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
562
0
     "%s: invalid MFT entry.",
563
0
     function );
564
565
0
    return( -1 );
566
0
  }
567
3.62k
  if( libfdata_vector_get_element_value_by_index(
568
3.62k
       mft->mft_entry_vector,
569
3.62k
       (intptr_t *) file_io_handle,
570
3.62k
       (libfdata_cache_t *) mft->mft_entry_cache,
571
3.62k
       (int) mft_entry_index,
572
3.62k
       (intptr_t **) &safe_mft_entry,
573
3.62k
       0,
574
3.62k
       error ) != 1 )
575
272
  {
576
272
    libcerror_error_set(
577
272
     error,
578
272
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
579
272
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
580
272
     "%s: unable to retrieve MFT entry: %" PRIu64 ".",
581
272
     function,
582
272
     mft_entry_index );
583
584
272
    return( -1 );
585
272
  }
586
3.35k
  if( libfsntfs_mft_entry_read_attributes(
587
3.35k
       safe_mft_entry,
588
3.35k
       mft->io_handle,
589
3.35k
       file_io_handle,
590
3.35k
       mft->mft_entry_vector,
591
3.35k
       mft->attribute_list_tree,
592
3.35k
       mft->flags,
593
3.35k
       error ) != 1 )
594
148
  {
595
148
    libcerror_error_set(
596
148
     error,
597
148
     LIBCERROR_ERROR_DOMAIN_IO,
598
148
     LIBCERROR_IO_ERROR_READ_FAILED,
599
148
     "%s: unable to read MFT entry: %d attributes.",
600
148
     function,
601
148
     mft_entry_index );
602
603
148
    return( -1 );
604
148
  }
605
3.20k
  *mft_entry = safe_mft_entry;
606
607
3.20k
  return( 1 );
608
3.35k
}
609
610
/* Retrieves the MFT entry for a specific index
611
 * Returns 1 if successful or -1 on error
612
 */
613
int libfsntfs_mft_get_mft_entry_by_index_no_cache(
614
     libfsntfs_mft_t *mft,
615
     libbfio_handle_t *file_io_handle,
616
     uint64_t mft_entry_index,
617
     libfsntfs_mft_entry_t **mft_entry,
618
     libcerror_error_t **error )
619
2.14k
{
620
2.14k
  libfsntfs_mft_entry_t *safe_mft_entry = NULL;
621
2.14k
  static char *function                 = "libfsntfs_mft_get_mft_entry_by_index_no_cache";
622
623
2.14k
  if( mft == NULL )
624
0
  {
625
0
    libcerror_error_set(
626
0
     error,
627
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
628
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
629
0
     "%s: invalid MFT.",
630
0
     function );
631
632
0
    return( -1 );
633
0
  }
634
2.14k
  if( mft_entry_index > mft->number_of_mft_entries )
635
3
  {
636
3
    libcerror_error_set(
637
3
     error,
638
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
639
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
640
3
     "%s: invalid MFT entry index value out of bounds.",
641
3
     function );
642
643
3
    return( -1 );
644
3
  }
645
2.13k
  if( mft_entry == NULL )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
650
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
651
0
     "%s: invalid MFT entry.",
652
0
     function );
653
654
0
    return( -1 );
655
0
  }
656
2.13k
  if( libfdata_vector_get_element_value_by_index(
657
2.13k
       mft->mft_entry_vector,
658
2.13k
       (intptr_t *) file_io_handle,
659
2.13k
       (libfdata_cache_t *) mft->single_mft_entry_cache,
660
2.13k
       (int) mft_entry_index,
661
2.13k
       (intptr_t **) &safe_mft_entry,
662
2.13k
       LIBFDATA_READ_FLAG_IGNORE_CACHE,
663
2.13k
       error ) != 1 )
664
8
  {
665
8
    libcerror_error_set(
666
8
     error,
667
8
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
668
8
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
669
8
     "%s: unable to retrieve MFT entry: %" PRIu64 ".",
670
8
     function,
671
8
     mft_entry_index );
672
673
8
    return( -1 );
674
8
  }
675
2.12k
  if( libfsntfs_mft_entry_read_attributes(
676
2.12k
       safe_mft_entry,
677
2.12k
       mft->io_handle,
678
2.12k
       file_io_handle,
679
2.12k
       mft->mft_entry_vector,
680
2.12k
       mft->attribute_list_tree,
681
2.12k
       mft->flags,
682
2.12k
       error ) != 1 )
683
9
  {
684
9
    libcerror_error_set(
685
9
     error,
686
9
     LIBCERROR_ERROR_DOMAIN_IO,
687
9
     LIBCERROR_IO_ERROR_READ_FAILED,
688
9
     "%s: unable to read MFT entry: %d attributes.",
689
9
     function,
690
9
     mft_entry_index );
691
692
9
    return( -1 );
693
9
  }
694
2.12k
  if( libfcache_cache_clear_value_by_index(
695
2.12k
       mft->single_mft_entry_cache,
696
2.12k
       0,
697
2.12k
       error ) != 1 )
698
0
  {
699
0
    libcerror_error_set(
700
0
     error,
701
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
702
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
703
0
     "%s: unable to clear single MFT entry cache entry: 0.",
704
0
     function );
705
706
0
    return( -1 );
707
0
  }
708
2.12k
  *mft_entry = safe_mft_entry;
709
710
2.12k
  return( 1 );
711
2.12k
}
712