Coverage Report

Created: 2025-10-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsntfs/libfsntfs/libfsntfs_mft_entry.c
Line
Count
Source
1
/*
2
 * Master File Table (MFT) entry 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_debug.h"
28
#include "libfsntfs_definitions.h"
29
#include "libfsntfs_directory_entry.h"
30
#include "libfsntfs_fixup_values.h"
31
#include "libfsntfs_io_handle.h"
32
#include "libfsntfs_libbfio.h"
33
#include "libfsntfs_libcdata.h"
34
#include "libfsntfs_libcerror.h"
35
#include "libfsntfs_libcnotify.h"
36
#include "libfsntfs_libfcache.h"
37
#include "libfsntfs_libfdata.h"
38
#include "libfsntfs_libuna.h"
39
#include "libfsntfs_mft_attribute.h"
40
#include "libfsntfs_mft_attribute_list.h"
41
#include "libfsntfs_mft_attribute_list_entry.h"
42
#include "libfsntfs_mft_entry.h"
43
#include "libfsntfs_mft_entry_header.h"
44
#include "libfsntfs_standard_information_values.h"
45
#include "libfsntfs_types.h"
46
#include "libfsntfs_unused.h"
47
48
#include "fsntfs_mft_entry.h"
49
50
const char fsntfs_mft_entry_signature[ 4 ] = { 'F', 'I', 'L', 'E' };
51
52
/* Checks if a buffer containing the MFT entry is filled with 0-byte values (empty-block)
53
 * Returns 1 if empty, 0 if not or -1 on error
54
 */
55
int libfsntfs_mft_entry_check_for_empty_block(
56
     const uint8_t *data,
57
     size_t data_size,
58
     libcerror_error_t **error )
59
35.9k
{
60
35.9k
  libfsntfs_aligned_t *aligned_data_index = NULL;
61
35.9k
  libfsntfs_aligned_t *aligned_data_start = NULL;
62
35.9k
  uint8_t *data_index                     = NULL;
63
35.9k
  uint8_t *data_start                     = NULL;
64
35.9k
  static char *function                   = "libfsntfs_mft_entry_check_for_empty_block";
65
66
35.9k
  if( data == NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
71
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
72
0
     "%s: invalid data.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
35.9k
  if( data_size > (size_t) SSIZE_MAX )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
82
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
83
0
     "%s: invalid data size value exceeds maximum.",
84
0
     function );
85
86
0
    return( -1 );
87
0
  }
88
35.9k
  data_start = (uint8_t *) data;
89
35.9k
  data_index = (uint8_t *) data + 1;
90
35.9k
  data_size -= 1;
91
92
  /* Only optimize for data larger than the alignment
93
   */
94
35.9k
  if( data_size > ( 2 * sizeof( libfsntfs_aligned_t ) ) )
95
35.9k
  {
96
    /* Align the data start
97
     */
98
35.9k
    while( ( (intptr_t) data_start % sizeof( libfsntfs_aligned_t ) ) != 0 )
99
0
    {
100
0
      if( *data_start != *data_index )
101
0
      {
102
0
        return( 0 );
103
0
      }
104
0
      data_start += 1;
105
0
      data_index += 1;
106
0
      data_size  -= 1;
107
0
    }
108
    /* Align the data index
109
     */
110
90.7k
    while( ( (intptr_t) data_index % sizeof( libfsntfs_aligned_t ) ) != 0 )
111
84.1k
    {
112
84.1k
      if( *data_start != *data_index )
113
29.4k
      {
114
29.4k
        return( 0 );
115
29.4k
      }
116
54.7k
      data_index += 1;
117
54.7k
      data_size  -= 1;
118
54.7k
    }
119
6.53k
    aligned_data_start = (libfsntfs_aligned_t *) data_start;
120
6.53k
    aligned_data_index = (libfsntfs_aligned_t *) data_index;
121
122
304k
    while( data_size > sizeof( libfsntfs_aligned_t ) )
123
302k
    {
124
302k
      if( *aligned_data_start != *aligned_data_index )
125
4.90k
      {
126
4.90k
        return( 0 );
127
4.90k
      }
128
298k
      aligned_data_index += 1;
129
298k
      data_size          -= sizeof( libfsntfs_aligned_t );
130
298k
    }
131
1.62k
    data_index = (uint8_t *) aligned_data_index;
132
1.62k
  }
133
12.7k
  while( data_size != 0 )
134
11.3k
  {
135
11.3k
    if( *data_start != *data_index )
136
278
    {
137
278
      return( 0 );
138
278
    }
139
11.1k
    data_index += 1;
140
11.1k
    data_size  -= 1;
141
11.1k
  }
142
1.34k
  return( 1 );
143
1.62k
}
144
145
/* Creates a MFT entry
146
 * Make sure the value mft_entry is referencing, is set to NULL
147
 * Returns 1 if successful or -1 on error
148
 */
149
int libfsntfs_mft_entry_initialize(
150
     libfsntfs_mft_entry_t **mft_entry,
151
     libcerror_error_t **error )
152
36.5k
{
153
36.5k
  static char *function = "libfsntfs_mft_entry_initialize";
154
155
36.5k
  if( mft_entry == NULL )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161
0
     "%s: invalid MFT entry.",
162
0
     function );
163
164
0
    return( -1 );
165
0
  }
166
36.5k
  if( *mft_entry != NULL )
167
0
  {
168
0
    libcerror_error_set(
169
0
     error,
170
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
171
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
172
0
     "%s: invalid MFT entry value already set.",
173
0
     function );
174
175
0
    return( -1 );
176
0
  }
177
36.5k
  *mft_entry = memory_allocate_structure(
178
36.5k
                libfsntfs_mft_entry_t );
179
180
36.5k
  if( *mft_entry == NULL )
181
0
  {
182
0
    libcerror_error_set(
183
0
     error,
184
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
185
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
186
0
     "%s: unable to create MFT entry.",
187
0
     function );
188
189
0
    goto on_error;
190
0
  }
191
36.5k
  if( memory_set(
192
36.5k
       *mft_entry,
193
36.5k
       0,
194
36.5k
       sizeof( libfsntfs_mft_entry_t ) ) == NULL )
195
0
  {
196
0
    libcerror_error_set(
197
0
     error,
198
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
199
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
200
0
     "%s: unable to clear MFT entry.",
201
0
     function );
202
203
0
    memory_free(
204
0
     *mft_entry );
205
206
0
    *mft_entry = NULL;
207
208
0
    return( -1 );
209
0
  }
210
36.5k
  if( libcdata_array_initialize(
211
36.5k
       &( ( *mft_entry )->attributes_array ),
212
36.5k
       0,
213
36.5k
       error ) != 1 )
214
0
  {
215
0
    libcerror_error_set(
216
0
     error,
217
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
218
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
219
0
     "%s: unable to create attributes array.",
220
0
     function );
221
222
0
    goto on_error;
223
0
  }
224
36.5k
  if( libcdata_array_initialize(
225
36.5k
       &( ( *mft_entry )->alternate_data_attributes_array ),
226
36.5k
       0,
227
36.5k
       error ) != 1 )
228
0
  {
229
0
    libcerror_error_set(
230
0
     error,
231
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
232
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
233
0
     "%s: unable to create alternate data attributes array.",
234
0
     function );
235
236
0
    goto on_error;
237
0
  }
238
36.5k
  ( *mft_entry )->file_name_attribute_index            = -1;
239
36.5k
  ( *mft_entry )->reparse_point_attribute_index        = -1;
240
36.5k
  ( *mft_entry )->security_descriptor_attribute_index  = -1;
241
36.5k
  ( *mft_entry )->standard_information_attribute_index = -1;
242
36.5k
  ( *mft_entry )->volume_information_attribute_index   = -1;
243
36.5k
  ( *mft_entry )->volume_name_attribute_index          = -1;
244
245
36.5k
  return( 1 );
246
247
0
on_error:
248
0
  if( *mft_entry != NULL )
249
0
  {
250
0
    if( ( *mft_entry )->alternate_data_attributes_array != NULL )
251
0
    {
252
0
      libcdata_array_free(
253
0
       &( ( *mft_entry )->alternate_data_attributes_array ),
254
0
       NULL,
255
0
       NULL );
256
0
    }
257
0
    if( ( *mft_entry )->attributes_array != NULL )
258
0
    {
259
0
      libcdata_array_free(
260
0
       &( ( *mft_entry )->attributes_array ),
261
0
       NULL,
262
0
       NULL );
263
0
    }
264
0
    memory_free(
265
0
     *mft_entry );
266
267
0
    *mft_entry = NULL;
268
0
  }
269
0
  return( -1 );
270
36.5k
}
271
272
/* Frees a MFT entry
273
 * Returns 1 if successful or -1 on error
274
 */
275
int libfsntfs_mft_entry_free(
276
     libfsntfs_mft_entry_t **mft_entry,
277
     libcerror_error_t **error )
278
36.5k
{
279
36.5k
  static char *function = "libfsntfs_mft_entry_free";
280
36.5k
  int result            = 1;
281
282
36.5k
  if( mft_entry == 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 MFT entry.",
289
0
     function );
290
291
0
    return( -1 );
292
0
  }
293
36.5k
  if( *mft_entry != NULL )
294
36.5k
  {
295
36.5k
    if( ( *mft_entry )->header != NULL )
296
34.4k
    {
297
34.4k
      if( libfsntfs_mft_entry_header_free(
298
34.4k
           &( ( *mft_entry )->header ),
299
34.4k
           error ) != 1 )
300
0
      {
301
0
        libcerror_error_set(
302
0
         error,
303
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
304
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
305
0
         "%s: unable to free MFT entry header.",
306
0
         function );
307
308
0
        result = -1;
309
0
      }
310
34.4k
    }
311
36.5k
    if( ( *mft_entry )->data != NULL )
312
20.6k
    {
313
20.6k
      memory_free(
314
20.6k
       ( *mft_entry )->data );
315
20.6k
    }
316
    /* The specific attribute references point to attributes in the array
317
     * and are freed by freeing the array and its values
318
     */
319
36.5k
    if( libcdata_array_free(
320
36.5k
         &( ( *mft_entry )->attributes_array ),
321
36.5k
         (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
322
36.5k
         error ) != 1 )
323
0
    {
324
0
      libcerror_error_set(
325
0
       error,
326
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
327
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
328
0
       "%s: unable to free attributes array.",
329
0
       function );
330
331
0
      result = -1;
332
0
    }
333
36.5k
    if( ( *mft_entry )->attribute_list != NULL )
334
1.45k
    {
335
1.45k
      if( libfsntfs_mft_attribute_list_free(
336
1.45k
           &( ( *mft_entry )->attribute_list ),
337
1.45k
           error ) != 1 )
338
0
      {
339
0
        libcerror_error_set(
340
0
         error,
341
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
343
0
         "%s: unable to free attribute list.",
344
0
         function );
345
346
0
        result = -1;
347
0
      }
348
1.45k
    }
349
    /* The alternate_data_attributes_array only contains references that are managed
350
     * by the attributes_array
351
     */
352
36.5k
    if( libcdata_array_free(
353
36.5k
         &( ( *mft_entry )->alternate_data_attributes_array ),
354
36.5k
         NULL,
355
36.5k
         error ) != 1 )
356
0
    {
357
0
      libcerror_error_set(
358
0
       error,
359
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
361
0
       "%s: unable to free alternate data attributes array.",
362
0
       function );
363
364
0
      result = -1;
365
0
    }
366
36.5k
    memory_free(
367
36.5k
     *mft_entry );
368
369
36.5k
    *mft_entry = NULL;
370
36.5k
  }
371
36.5k
  return( result );
372
36.5k
}
373
374
/* Reads the MFT entry
375
 * Returns 1 if successful, 0 if empty or marked as bad, or -1 on error
376
 */
377
int libfsntfs_mft_entry_read_data(
378
     libfsntfs_mft_entry_t *mft_entry,
379
     uint8_t *data,
380
     size_t data_size,
381
     uint32_t mft_entry_index,
382
     libcerror_error_t **error )
383
35.9k
{
384
35.9k
  static char *function           = "libfsntfs_mft_entry_read_data";
385
35.9k
  size_t data_offset              = 0;
386
35.9k
  size_t unknown_data_size        = 0;
387
35.9k
  uint16_t attributes_offset      = 0;
388
35.9k
  uint16_t fixup_values_offset    = 0;
389
35.9k
  uint16_t number_of_fixup_values = 0;
390
35.9k
  int result                      = 0;
391
392
#if defined( HAVE_DEBUG_OUTPUT )
393
  uint16_t total_entry_size       = 0;
394
#endif
395
396
35.9k
  if( mft_entry == NULL )
397
0
  {
398
0
    libcerror_error_set(
399
0
     error,
400
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
401
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
402
0
     "%s: invalid MFT entry.",
403
0
     function );
404
405
0
    return( -1 );
406
0
  }
407
35.9k
  if( mft_entry->header != NULL )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
413
0
     "%s: invalid MFT entry - header value already set.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
35.9k
  if( data == NULL )
419
0
  {
420
0
    libcerror_error_set(
421
0
     error,
422
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
423
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
424
0
     "%s: invalid data.",
425
0
     function );
426
427
0
    return( -1 );
428
0
  }
429
35.9k
  if( data_size > (size_t) SSIZE_MAX )
430
0
  {
431
0
    libcerror_error_set(
432
0
     error,
433
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
434
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
435
0
     "%s: invalid data size value exceeds maximum.",
436
0
     function );
437
438
0
    return( -1 );
439
0
  }
440
35.9k
  result = libfsntfs_mft_entry_check_for_empty_block(
441
35.9k
            data,
442
35.9k
            data_size,
443
35.9k
            error );
444
445
35.9k
  if( result == -1 )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
450
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
451
0
     "%s: unable to determine if MFT entry is empty.",
452
0
     function );
453
454
0
    goto on_error;
455
0
  }
456
35.9k
  else if( result != 0 )
457
1.34k
  {
458
#if defined( HAVE_DEBUG_OUTPUT )
459
    if( libcnotify_verbose != 0 )
460
    {
461
      libcnotify_printf(
462
       "%s: MFT entry: %" PRIu32 " is empty.\n",
463
       function,
464
       mft_entry_index );
465
    }
466
#endif
467
1.34k
    mft_entry->is_empty = 1;
468
469
1.34k
    return( 0 );
470
1.34k
  }
471
34.6k
  if( libfsntfs_mft_entry_header_initialize(
472
34.6k
       &( mft_entry->header ),
473
34.6k
       error ) != 1 )
474
0
  {
475
0
    libcerror_error_set(
476
0
     error,
477
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
478
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
479
0
     "%s: unable to create MFT entry header.",
480
0
     function );
481
482
0
    goto on_error;
483
0
  }
484
34.6k
  result = libfsntfs_mft_entry_header_read_data(
485
34.6k
            mft_entry->header,
486
34.6k
            data,
487
34.6k
            data_size,
488
34.6k
            error );
489
490
34.6k
  if( result == -1 )
491
28
  {
492
28
    libcerror_error_set(
493
28
     error,
494
28
     LIBCERROR_ERROR_DOMAIN_IO,
495
28
     LIBCERROR_IO_ERROR_READ_FAILED,
496
28
     "%s: unable to read MFT entry header.",
497
28
     function );
498
499
28
    goto on_error;
500
28
  }
501
34.6k
  else if( result == 0 )
502
13.8k
  {
503
    /* Note that an empty MFT data can contain arbitrary data
504
     */
505
13.8k
    mft_entry->is_empty = 1;
506
507
13.8k
    return( 0 );
508
13.8k
  }
509
#if defined( HAVE_DEBUG_OUTPUT )
510
  if( libcnotify_verbose != 0 )
511
  {
512
    if( libfsntfs_mft_entry_header_get_total_entry_size(
513
         mft_entry->header,
514
         &total_entry_size,
515
         error ) != 1 )
516
    {
517
      libcerror_error_set(
518
       error,
519
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
521
       "%s: unable to retrieve total entry size.",
522
       function );
523
524
      goto on_error;
525
    }
526
    if( data_size != (size_t) total_entry_size )
527
    {
528
      libcnotify_printf(
529
       "%s: mismatch in total MFT entry size (calculated: %" PRIzd ", stored: %" PRIu16 ").\n",
530
       function,
531
       data_size,
532
       total_entry_size );
533
    }
534
  }
535
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
536
537
20.7k
  if( libfsntfs_mft_entry_header_get_attributes_offset(
538
20.7k
       mft_entry->header,
539
20.7k
       &attributes_offset,
540
20.7k
       error ) != 1 )
541
0
  {
542
0
    libcerror_error_set(
543
0
     error,
544
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
545
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
546
0
     "%s: unable to retrieve attributes offset.",
547
0
     function );
548
549
0
    goto on_error;
550
0
  }
551
20.7k
  if( attributes_offset >= data_size )
552
28
  {
553
28
    libcerror_error_set(
554
28
     error,
555
28
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
556
28
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
557
28
     "%s: invalid attributes offset value out of bounds.",
558
28
     function );
559
560
28
    goto on_error;
561
28
  }
562
20.7k
  if( libfsntfs_mft_entry_header_get_fixup_values_offset(
563
20.7k
       mft_entry->header,
564
20.7k
       &fixup_values_offset,
565
20.7k
       error ) != 1 )
566
0
  {
567
0
    libcerror_error_set(
568
0
     error,
569
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
570
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
571
0
     "%s: unable to retrieve fix-up values offset.",
572
0
     function );
573
574
0
    goto on_error;
575
0
  }
576
20.7k
  if( fixup_values_offset > attributes_offset )
577
54
  {
578
54
    libcerror_error_set(
579
54
     error,
580
54
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
581
54
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
582
54
     "%s: fix-up values offset exceeds attributes offset.",
583
54
     function );
584
585
54
    goto on_error;
586
54
  }
587
20.6k
  if( fixup_values_offset > 42 )
588
18.5k
  {
589
18.5k
    data_offset = sizeof( fsntfs_mft_entry_header_t );
590
18.5k
  }
591
2.15k
  else
592
2.15k
  {
593
    /* In NTFS 1.2 the fix-up values offset can point to wfixupPattern
594
     */
595
2.15k
    data_offset = 42;
596
2.15k
  }
597
20.6k
  if( data_offset < fixup_values_offset )
598
12.4k
  {
599
12.4k
    unknown_data_size = (size_t) fixup_values_offset - data_offset;
600
601
#if defined( HAVE_DEBUG_OUTPUT )
602
    if( libcnotify_verbose != 0 )
603
    {
604
      libcnotify_printf(
605
       "%s: unknown data:\n",
606
       function );
607
      libcnotify_print_data(
608
       &( data[ data_offset ] ),
609
       unknown_data_size,
610
       0 );
611
    }
612
#endif
613
12.4k
    data_offset += unknown_data_size;
614
12.4k
  }
615
20.6k
  if( libfsntfs_mft_entry_header_get_number_of_fixup_values(
616
20.6k
       mft_entry->header,
617
20.6k
       &number_of_fixup_values,
618
20.6k
       error ) != 1 )
619
0
  {
620
0
    libcerror_error_set(
621
0
     error,
622
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
623
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
624
0
     "%s: unable to retrieve number of fix-up values.",
625
0
     function );
626
627
0
    goto on_error;
628
0
  }
629
20.6k
  if( number_of_fixup_values > 0 )
630
13.6k
  {
631
13.6k
    if( libfsntfs_fixup_values_apply(
632
13.6k
         data,
633
13.6k
         data_size,
634
13.6k
         fixup_values_offset,
635
13.6k
         number_of_fixup_values,
636
13.6k
         error ) != 1 )
637
62
    {
638
62
      libcerror_error_set(
639
62
       error,
640
62
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
641
62
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
642
62
       "%s: unable to apply fix-up values.",
643
62
       function );
644
645
62
      goto on_error;
646
62
    }
647
13.6k
    data_offset += 2 + ( (size_t) number_of_fixup_values * 2 );
648
13.6k
  }
649
#if defined( HAVE_DEBUG_OUTPUT )
650
  if( libcnotify_verbose != 0 )
651
  {
652
    if( data_offset < attributes_offset )
653
    {
654
      libcnotify_printf(
655
       "%s: unknown data:\n",
656
       function );
657
      libcnotify_print_data(
658
       &( data[ data_offset ] ),
659
       (size_t) attributes_offset - data_offset,
660
       0 );
661
    }
662
  }
663
#endif
664
20.6k
  mft_entry->is_empty = 0;
665
666
20.6k
  mft_entry->index = mft_entry->header->index;
667
668
20.6k
  if( mft_entry->index != mft_entry_index )
669
18.0k
  {
670
18.0k
    mft_entry->index = mft_entry_index;
671
18.0k
  }
672
20.6k
  mft_entry->file_reference = ( (uint64_t) mft_entry->header->sequence << 48 ) | mft_entry->index;
673
674
20.6k
  return( 1 );
675
676
172
on_error:
677
172
  if( mft_entry->header != NULL )
678
172
  {
679
172
    libfsntfs_mft_entry_header_free(
680
172
     &( mft_entry->header ),
681
172
     NULL );
682
172
  }
683
172
  return( -1 );
684
20.6k
}
685
686
/* Reads the MFT entry
687
 * Returns 1 if successful or -1 on error
688
 */
689
int libfsntfs_mft_entry_read_file_io_handle(
690
     libfsntfs_mft_entry_t *mft_entry,
691
     libbfio_handle_t *file_io_handle,
692
     off64_t file_offset,
693
     uint32_t mft_entry_size,
694
     uint32_t mft_entry_index,
695
     libcerror_error_t **error )
696
36.5k
{
697
36.5k
  static char *function = "libfsntfs_mft_entry_read_file_io_handle";
698
36.5k
  ssize_t read_count    = 0;
699
36.5k
  int result            = 0;
700
701
36.5k
  if( mft_entry == NULL )
702
0
  {
703
0
    libcerror_error_set(
704
0
     error,
705
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
706
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
707
0
     "%s: invalid MFT entry.",
708
0
     function );
709
710
0
    return( -1 );
711
0
  }
712
36.5k
  if( mft_entry->data != NULL )
713
0
  {
714
0
    libcerror_error_set(
715
0
     error,
716
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
717
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
718
0
     "%s: invalid MFT entry - data value already set.",
719
0
     function );
720
721
0
    return( -1 );
722
0
  }
723
36.5k
  if( ( (size_t) mft_entry_size <= 42 )
724
36.5k
   || ( (size_t) mft_entry_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
725
0
  {
726
0
    libcerror_error_set(
727
0
     error,
728
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
729
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
730
0
     "%s: invalid MFT entry size value out of bounds.",
731
0
     function );
732
733
0
    goto on_error;
734
0
  }
735
36.5k
  mft_entry->data = (uint8_t *) memory_allocate(
736
36.5k
                                 (size_t) mft_entry_size );
737
738
36.5k
  if( mft_entry->data == NULL )
739
0
  {
740
0
    libcerror_error_set(
741
0
     error,
742
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
743
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
744
0
     "%s: unable to create MFT entry data.",
745
0
     function );
746
747
0
    goto on_error;
748
0
  }
749
36.5k
  mft_entry->data_size = (size_t) mft_entry_size;
750
751
#if defined( HAVE_DEBUG_OUTPUT )
752
  if( libcnotify_verbose != 0 )
753
  {
754
    libcnotify_printf(
755
     "%s: reading MFT entry at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
756
     function,
757
     file_offset,
758
     file_offset );
759
  }
760
#endif
761
36.5k
  read_count = libbfio_handle_read_buffer_at_offset(
762
36.5k
                file_io_handle,
763
36.5k
                mft_entry->data,
764
36.5k
                mft_entry->data_size,
765
36.5k
                file_offset,
766
36.5k
                error );
767
768
36.5k
  if( read_count != (ssize_t) mft_entry->data_size )
769
504
  {
770
504
    libcerror_error_set(
771
504
     error,
772
504
     LIBCERROR_ERROR_DOMAIN_IO,
773
504
     LIBCERROR_IO_ERROR_READ_FAILED,
774
504
     "%s: unable to read MFT entry data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
775
504
     function,
776
504
     file_offset,
777
504
     file_offset );
778
779
504
    goto on_error;
780
504
  }
781
35.9k
  result = libfsntfs_mft_entry_read_data(
782
35.9k
            mft_entry,
783
35.9k
            mft_entry->data,
784
35.9k
            mft_entry->data_size,
785
35.9k
            mft_entry_index,
786
35.9k
            error );
787
788
35.9k
  if( result == -1 )
789
172
  {
790
172
    libcerror_error_set(
791
172
     error,
792
172
     LIBCERROR_ERROR_DOMAIN_IO,
793
172
     LIBCERROR_IO_ERROR_READ_FAILED,
794
172
     "%s: unable to read MFT entry data.",
795
172
     function );
796
797
172
    goto on_error;
798
172
  }
799
35.8k
  else if( result == 0 )
800
15.2k
  {
801
15.2k
    memory_free(
802
15.2k
     mft_entry->data );
803
804
15.2k
    mft_entry->data      = NULL;
805
15.2k
    mft_entry->data_size = 0;
806
15.2k
  }
807
35.8k
  return( 1 );
808
809
676
on_error:
810
676
  if( mft_entry->header != NULL )
811
0
  {
812
0
    libfsntfs_mft_entry_header_free(
813
0
     &( mft_entry->header ),
814
0
     NULL );
815
0
  }
816
676
  if( mft_entry->data != NULL )
817
676
  {
818
676
    memory_free(
819
676
     mft_entry->data );
820
821
676
    mft_entry->data = NULL;
822
676
  }
823
676
  mft_entry->data_size = 0;
824
825
676
  return( -1 );
826
35.9k
}
827
828
/* Reads the MFT attributes
829
 * Returns 1 if successful or -1 on error
830
 */
831
int libfsntfs_mft_entry_read_attributes_data(
832
     libfsntfs_mft_entry_t *mft_entry,
833
     libfsntfs_io_handle_t *io_handle,
834
     const uint8_t *data,
835
     size_t data_size,
836
     libcerror_error_t **error )
837
14.7k
{
838
14.7k
  libfsntfs_mft_attribute_t *mft_attribute = NULL;
839
14.7k
  static char *function                    = "libfsntfs_mft_entry_read_attributes_data";
840
14.7k
  size_t data_offset                       = 0;
841
14.7k
  uint32_t attribute_type                  = 0;
842
14.7k
  uint16_t attributes_offset               = 0;
843
14.7k
  int attribute_index                      = 0;
844
14.7k
  int entry_index                          = 0;
845
846
#if defined( HAVE_DEBUG_OUTPUT )
847
  uint16_t used_entry_size                 = 0;
848
#endif
849
850
14.7k
  if( mft_entry == NULL )
851
0
  {
852
0
    libcerror_error_set(
853
0
     error,
854
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856
0
     "%s: invalid MFT entry.",
857
0
     function );
858
859
0
    return( -1 );
860
0
  }
861
14.7k
  if( data == NULL )
862
9
  {
863
9
    libcerror_error_set(
864
9
     error,
865
9
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
866
9
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
867
9
     "%s: invalid data.",
868
9
     function );
869
870
9
    return( -1 );
871
9
  }
872
14.6k
  if( data_size > (size_t) SSIZE_MAX )
873
0
  {
874
0
    libcerror_error_set(
875
0
     error,
876
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
877
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
878
0
     "%s: invalid data size value exceeds maximum.",
879
0
     function );
880
881
0
    return( -1 );
882
0
  }
883
14.6k
  if( data_size < 4 )
884
0
  {
885
0
    libcerror_error_set(
886
0
     error,
887
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
888
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
889
0
     "%s: unsupported data size value too small\n",
890
0
     function );
891
892
0
    return( -1 );
893
0
  }
894
14.6k
  if( libfsntfs_mft_entry_header_get_attributes_offset(
895
14.6k
       mft_entry->header,
896
14.6k
       &attributes_offset,
897
14.6k
       error ) != 1 )
898
0
  {
899
0
    libcerror_error_set(
900
0
     error,
901
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
902
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
903
0
     "%s: unable to retrieve attributes offset.",
904
0
     function );
905
906
0
    goto on_error;
907
0
  }
908
14.6k
  data_offset = (size_t) attributes_offset;
909
910
14.6k
  do
911
66.9k
  {
912
66.9k
    if( data_offset > ( data_size - 4 ) )
913
85
    {
914
85
      libcerror_error_set(
915
85
       error,
916
85
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
917
85
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
918
85
       "%s: invalid MFT entry - attribute offset: %d value out of bounds.",
919
85
       function,
920
85
       attribute_index );
921
922
85
      goto on_error;
923
85
    }
924
66.8k
    byte_stream_copy_to_uint32_little_endian(
925
66.8k
     &( data[ data_offset ] ),
926
66.8k
     attribute_type );
927
928
66.8k
    if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES )
929
13.2k
    {
930
13.2k
      break;
931
13.2k
    }
932
53.6k
    if( libfsntfs_mft_attribute_initialize(
933
53.6k
         &mft_attribute,
934
53.6k
         error ) != 1 )
935
0
    {
936
0
      libcerror_error_set(
937
0
       error,
938
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
939
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
940
0
       "%s: unable to create MFT attribute: %d.",
941
0
       function,
942
0
       attribute_index );
943
944
0
      goto on_error;
945
0
    }
946
53.6k
    if( libfsntfs_mft_attribute_read_data(
947
53.6k
         mft_attribute,
948
53.6k
         io_handle,
949
53.6k
         &( data[ data_offset ] ),
950
53.6k
         data_size - data_offset,
951
53.6k
         error ) != 1 )
952
1.15k
    {
953
1.15k
      libcerror_error_set(
954
1.15k
       error,
955
1.15k
       LIBCERROR_ERROR_DOMAIN_IO,
956
1.15k
       LIBCERROR_IO_ERROR_READ_FAILED,
957
1.15k
       "%s: unable to read MFT attribute: %d of type: 0x%08" PRIx32 ".",
958
1.15k
       function,
959
1.15k
       attribute_index,
960
1.15k
       attribute_type );
961
962
1.15k
      goto on_error;
963
1.15k
    }
964
52.4k
    data_offset += mft_attribute->size;
965
966
52.4k
    if( attribute_type == LIBFSNTFS_ATTRIBUTE_TYPE_ATTRIBUTE_LIST )
967
5.10k
    {
968
5.10k
      if( mft_entry->list_attribute != NULL )
969
61
      {
970
61
        libcerror_error_set(
971
61
         error,
972
61
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
973
61
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
974
61
         "%s: invalid MFT entry - list attribute value already set.",
975
61
         function );
976
977
61
        goto on_error;
978
61
      }
979
5.03k
      mft_entry->list_attribute = mft_attribute;
980
5.03k
    }
981
    /* mft_entry->attributes_array takes over management of mft_attribute
982
     */
983
52.4k
    if( libcdata_array_append_entry(
984
52.4k
         mft_entry->attributes_array,
985
52.4k
         &entry_index,
986
52.4k
         (intptr_t *) mft_attribute,
987
52.4k
         error ) != 1 )
988
0
    {
989
0
      libcerror_error_set(
990
0
       error,
991
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
992
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
993
0
       "%s: unable to append attribute to array.",
994
0
       function );
995
996
0
      goto on_error;
997
0
    }
998
52.4k
    if( libfsntfs_mft_entry_set_attribute_helper_values(
999
52.4k
         mft_entry,
1000
52.4k
         entry_index,
1001
52.4k
         mft_attribute,
1002
52.4k
         error ) != 1 )
1003
137
    {
1004
137
      libcerror_error_set(
1005
137
       error,
1006
137
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1007
137
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1008
137
       "%s: unable to set helper values for attribute: %d.",
1009
137
       function,
1010
137
       attribute_index );
1011
1012
137
      mft_attribute = NULL;
1013
1014
137
      goto on_error;
1015
137
    }
1016
52.2k
    mft_attribute = NULL;
1017
1018
52.2k
    attribute_index++;
1019
52.2k
  }
1020
52.2k
  while( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_END_OF_ATTRIBUTES );
1021
1022
13.2k
  data_offset += 4;
1023
1024
#if defined( HAVE_DEBUG_OUTPUT )
1025
  if( libcnotify_verbose != 0 )
1026
  {
1027
    if( libfsntfs_mft_entry_header_get_used_entry_size(
1028
         mft_entry->header,
1029
         &used_entry_size,
1030
         error ) != 1 )
1031
    {
1032
      libcerror_error_set(
1033
       error,
1034
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1035
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1036
       "%s: unable to retrieve used entry size.",
1037
       function );
1038
1039
      goto on_error;
1040
    }
1041
    if( data_offset != (size_t) used_entry_size )
1042
    {
1043
      libcnotify_printf(
1044
       "%s: mismatch in used MFT entry size (calculated: %" PRIzd ", stored: %" PRIu16 ").\n",
1045
       function,
1046
       data_offset,
1047
       used_entry_size );
1048
    }
1049
  }
1050
#endif
1051
13.2k
  return( 1 );
1052
1053
1.43k
on_error:
1054
1.43k
  if( mft_attribute != NULL )
1055
1.21k
  {
1056
1.21k
    libfsntfs_mft_attribute_free(
1057
1.21k
     &mft_attribute,
1058
1.21k
     NULL );
1059
1.21k
  }
1060
1.43k
  libcdata_array_empty(
1061
1.43k
   mft_entry->attributes_array,
1062
1.43k
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
1063
1.43k
   NULL );
1064
1065
1.43k
  mft_entry->file_name_attribute_index            = -1;
1066
1.43k
  mft_entry->reparse_point_attribute_index        = -1;
1067
1.43k
  mft_entry->security_descriptor_attribute_index  = -1;
1068
1.43k
  mft_entry->standard_information_attribute_index = -1;
1069
1.43k
  mft_entry->volume_information_attribute_index   = -1;
1070
1.43k
  mft_entry->volume_name_attribute_index          = -1;
1071
1.43k
  mft_entry->list_attribute                       = NULL;
1072
1.43k
  mft_entry->data_attribute                       = NULL;
1073
1.43k
  mft_entry->wof_compressed_data_attribute        = NULL;
1074
1075
1.43k
  return( -1 );
1076
14.6k
}
1077
1078
/* Reads the MFT attributes
1079
 * Returns 1 if successful or -1 on error
1080
 */
1081
int libfsntfs_mft_entry_read_attributes(
1082
     libfsntfs_mft_entry_t *mft_entry,
1083
     libfsntfs_io_handle_t *io_handle,
1084
     libbfio_handle_t *file_io_handle,
1085
     libfdata_vector_t *mft_entry_vector,
1086
     libcdata_btree_t *attribute_list_tree,
1087
     uint8_t flags,
1088
     libcerror_error_t **error )
1089
5.17k
{
1090
5.17k
  libcdata_tree_node_t *upper_node                      = NULL;
1091
5.17k
  libfsntfs_mft_attribute_list_t *attribute_list        = NULL;
1092
5.17k
  libfsntfs_mft_attribute_list_t *lookup_attribute_list = NULL;
1093
5.17k
  static char *function                                 = "libfsntfs_mft_entry_read_attributes";
1094
5.17k
  int result                                            = 0;
1095
1096
5.17k
  if( mft_entry == NULL )
1097
0
  {
1098
0
    libcerror_error_set(
1099
0
     error,
1100
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1101
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1102
0
     "%s: invalid MFT entry.",
1103
0
     function );
1104
1105
0
    return( -1 );
1106
0
  }
1107
5.17k
  if( mft_entry->attributes_read != 0 )
1108
0
  {
1109
0
    return( 1 );
1110
0
  }
1111
5.17k
  if( mft_entry->is_empty == 0 )
1112
5.15k
  {
1113
5.15k
    if( libfsntfs_mft_entry_read_attributes_data(
1114
5.15k
         mft_entry,
1115
5.15k
         io_handle,
1116
5.15k
         mft_entry->data,
1117
5.15k
         mft_entry->data_size,
1118
5.15k
         error ) != 1 )
1119
60
    {
1120
60
      libcerror_error_set(
1121
60
       error,
1122
60
       LIBCERROR_ERROR_DOMAIN_IO,
1123
60
       LIBCERROR_IO_ERROR_READ_FAILED,
1124
60
       "%s: unable to read attributes of MFT entry: %d.",
1125
60
       function,
1126
60
       mft_entry->index );
1127
1128
60
      goto on_error;
1129
60
    }
1130
5.09k
    if( mft_entry->list_attribute != NULL )
1131
436
    {
1132
436
      if( ( flags & LIBFSNTFS_FILE_ENTRY_FLAGS_MFT_ONLY ) != 0 )
1133
0
      {
1134
0
        if( libfsntfs_mft_attribute_list_initialize(
1135
0
             &lookup_attribute_list,
1136
0
             mft_entry->file_reference,
1137
0
             error ) != 1 )
1138
0
        {
1139
0
          libcerror_error_set(
1140
0
           error,
1141
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1142
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1143
0
           "%s: unable to create lookup attribute list.",
1144
0
           function );
1145
1146
0
          goto on_error;
1147
0
        }
1148
0
        result = libcdata_btree_get_value_by_value(
1149
0
                  attribute_list_tree,
1150
0
                  (intptr_t *) lookup_attribute_list,
1151
0
                  (int (*)(intptr_t *, intptr_t *, libcerror_error_t **)) &libfsntfs_mft_attribute_list_compare_by_base_record_file_reference,
1152
0
                  &upper_node,
1153
0
                  (intptr_t **) &attribute_list,
1154
0
                  error );
1155
1156
0
        if( result == -1 )
1157
0
        {
1158
0
          libcerror_error_set(
1159
0
           error,
1160
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1161
0
           LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1162
0
           "%s: unable to retrieve path hint from tree.",
1163
0
           function );
1164
1165
0
          goto on_error;
1166
0
        }
1167
0
        if( libfsntfs_mft_attribute_list_free(
1168
0
             &lookup_attribute_list,
1169
0
             error ) != 1 )
1170
0
        {
1171
0
          libcerror_error_set(
1172
0
           error,
1173
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1174
0
           LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1175
0
           "%s: unable to free lookup attribute list.",
1176
0
           function );
1177
1178
0
          goto on_error;
1179
0
        }
1180
0
      }
1181
436
      else
1182
436
      {
1183
436
        if( libfsntfs_mft_entry_read_attribute_list(
1184
436
             mft_entry,
1185
436
             io_handle,
1186
436
             file_io_handle,
1187
436
             error ) != 1 )
1188
9
        {
1189
9
          libcerror_error_set(
1190
9
           error,
1191
9
           LIBCERROR_ERROR_DOMAIN_IO,
1192
9
           LIBCERROR_IO_ERROR_READ_FAILED,
1193
9
           "%s: unable to read attribute list.",
1194
9
           function );
1195
1196
9
          goto on_error;
1197
9
        }
1198
427
        attribute_list = mft_entry->attribute_list;
1199
427
      }
1200
427
      if( attribute_list != NULL )
1201
427
      {
1202
427
        if( libfsntfs_mft_entry_read_attribute_list_data_mft_entries(
1203
427
             mft_entry,
1204
427
             attribute_list,
1205
427
             io_handle,
1206
427
             file_io_handle,
1207
427
             mft_entry_vector,
1208
427
             error ) != 1 )
1209
66
        {
1210
66
          libcerror_error_set(
1211
66
           error,
1212
66
           LIBCERROR_ERROR_DOMAIN_IO,
1213
66
           LIBCERROR_IO_ERROR_READ_FAILED,
1214
66
           "%s: unable to read attribute list data MFT entries.",
1215
66
           function );
1216
1217
66
          goto on_error;
1218
66
        }
1219
427
      }
1220
0
      else
1221
0
      {
1222
0
        mft_entry->is_corrupted = 1;
1223
0
      }
1224
427
    }
1225
5.09k
  }
1226
5.04k
  mft_entry->attributes_read = 1;
1227
1228
5.04k
  return( 1 );
1229
1230
135
on_error:
1231
135
  if( lookup_attribute_list != NULL )
1232
0
  {
1233
0
    libfsntfs_mft_attribute_list_free(
1234
0
     &lookup_attribute_list,
1235
0
     NULL );
1236
0
  }
1237
135
  if( mft_entry->attribute_list != NULL )
1238
66
  {
1239
66
    libfsntfs_mft_attribute_list_free(
1240
66
     &( mft_entry->attribute_list ),
1241
66
     NULL );
1242
66
  }
1243
135
  libcdata_array_empty(
1244
135
   mft_entry->alternate_data_attributes_array,
1245
135
   NULL,
1246
135
   NULL );
1247
1248
135
  libcdata_array_empty(
1249
135
   mft_entry->attributes_array,
1250
135
   (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_attribute_free,
1251
135
   NULL );
1252
1253
135
  return( -1 );
1254
5.17k
}
1255
1256
/* Reads the attribute list
1257
 * Returns 1 if successful or -1 on error
1258
 */
1259
int libfsntfs_mft_entry_read_attribute_list(
1260
     libfsntfs_mft_entry_t *mft_entry,
1261
     libfsntfs_io_handle_t *io_handle,
1262
     libbfio_handle_t *file_io_handle,
1263
     libcerror_error_t **error )
1264
4.35k
{
1265
4.35k
  libfsntfs_mft_attribute_list_entry_t *attribute_list_entry = NULL;
1266
4.35k
  static char *function                                      = "libfsntfs_mft_entry_read_attribute_list";
1267
4.35k
  uint64_t attribute_list_data_mft_entry_index               = 0;
1268
4.35k
  uint64_t file_reference                                    = 0;
1269
4.35k
  int attribute_list_entry_index                             = 0;
1270
4.35k
  int number_of_attribute_list_entries                       = 0;
1271
1272
4.35k
  if( mft_entry == NULL )
1273
0
  {
1274
0
    libcerror_error_set(
1275
0
     error,
1276
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1277
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1278
0
     "%s: invalid MFT entry.",
1279
0
     function );
1280
1281
0
    return( -1 );
1282
0
  }
1283
4.35k
  if( mft_entry->list_attribute == NULL )
1284
0
  {
1285
0
    libcerror_error_set(
1286
0
     error,
1287
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1288
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1289
0
     "%s: invalid MFT entry - missing list attribute.",
1290
0
     function );
1291
1292
0
    return( -1 );
1293
0
  }
1294
4.35k
  if( mft_entry->attribute_list != NULL )
1295
0
  {
1296
0
    libcerror_error_set(
1297
0
     error,
1298
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1299
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
1300
0
     "%s: invalid MFT entry - attribute list value already set.",
1301
0
     function );
1302
1303
0
    return( -1 );
1304
0
  }
1305
4.35k
  if( libfsntfs_mft_attribute_list_initialize(
1306
4.35k
       &( mft_entry->attribute_list ),
1307
4.35k
       mft_entry->file_reference,
1308
4.35k
       error ) != 1 )
1309
0
  {
1310
0
    libcerror_error_set(
1311
0
     error,
1312
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1313
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1314
0
     "%s: unable to create attribute list.",
1315
0
     function );
1316
1317
0
    goto on_error;
1318
0
  }
1319
4.35k
  if( libfsntfs_mft_attribute_list_read_from_attribute(
1320
4.35k
       mft_entry->attribute_list,
1321
4.35k
       io_handle,
1322
4.35k
       file_io_handle,
1323
4.35k
       mft_entry->list_attribute,
1324
4.35k
       error ) != 1 )
1325
2.76k
  {
1326
2.76k
    libcerror_error_set(
1327
2.76k
     error,
1328
2.76k
     LIBCERROR_ERROR_DOMAIN_IO,
1329
2.76k
     LIBCERROR_IO_ERROR_READ_FAILED,
1330
2.76k
     "%s: unable to read attribute list.",
1331
2.76k
     function );
1332
1333
2.76k
    goto on_error;
1334
2.76k
  }
1335
1.58k
  if( libfsntfs_mft_attribute_list_get_number_of_entries(
1336
1.58k
       mft_entry->attribute_list,
1337
1.58k
       &number_of_attribute_list_entries,
1338
1.58k
       error ) != 1 )
1339
0
  {
1340
0
    libcerror_error_set(
1341
0
     error,
1342
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1343
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1344
0
     "%s: unable to retrieve number of attribute list entries.",
1345
0
     function );
1346
1347
0
    goto on_error;
1348
0
  }
1349
1.58k
  for( attribute_list_entry_index = 0;
1350
5.28k
       attribute_list_entry_index < number_of_attribute_list_entries;
1351
3.70k
       attribute_list_entry_index++ )
1352
3.76k
  {
1353
3.76k
    if( libfsntfs_mft_attribute_list_get_entry_by_index(
1354
3.76k
         mft_entry->attribute_list,
1355
3.76k
         attribute_list_entry_index,
1356
3.76k
         &attribute_list_entry,
1357
3.76k
         error ) != 1 )
1358
0
    {
1359
0
      libcerror_error_set(
1360
0
       error,
1361
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1362
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1363
0
       "%s: unable to retrieve attribute list entry: %d.",
1364
0
       function,
1365
0
       attribute_list_entry_index );
1366
1367
0
      goto on_error;
1368
0
    }
1369
3.76k
    if( libfsntfs_mft_attribute_list_entry_get_file_reference(
1370
3.76k
         attribute_list_entry,
1371
3.76k
         &file_reference,
1372
3.76k
         error ) != 1 )
1373
0
    {
1374
0
      libcerror_error_set(
1375
0
       error,
1376
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1377
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1378
0
       "%s: unable to retrieve attribute list entry: %d file reference.",
1379
0
       function,
1380
0
       attribute_list_entry_index );
1381
1382
0
      goto on_error;
1383
0
    }
1384
3.76k
    attribute_list_data_mft_entry_index = file_reference & 0xffffffffffffUL;
1385
1386
3.76k
    if( attribute_list_data_mft_entry_index > (uint64_t) INT_MAX )
1387
64
    {
1388
64
      libcerror_error_set(
1389
64
       error,
1390
64
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1391
64
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1392
64
       "%s: attribute list data MFT entry reference value out of bounds.",
1393
64
       function );
1394
1395
64
      goto on_error;
1396
64
    }
1397
    /* Ignore the current MFT entry
1398
     */
1399
3.70k
    if( attribute_list_data_mft_entry_index == (uint64_t) mft_entry->index )
1400
495
    {
1401
495
      continue;
1402
495
    }
1403
3.20k
    if( libfsntfs_mft_attribute_list_insert_file_reference(
1404
3.20k
         mft_entry->attribute_list,
1405
3.20k
         file_reference,
1406
3.20k
         error ) == -1 )
1407
0
    {
1408
0
      libcerror_error_set(
1409
0
       error,
1410
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1411
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1412
0
       "%s: unable to insert attribute list data file reference in attribute list.",
1413
0
       function );
1414
1415
0
      goto on_error;
1416
0
    }
1417
3.20k
  }
1418
1.52k
  return( 1 );
1419
1420
2.83k
on_error:
1421
2.83k
  if( mft_entry->attribute_list != NULL )
1422
2.83k
  {
1423
2.83k
    libfsntfs_mft_attribute_list_free(
1424
2.83k
     &( mft_entry->attribute_list ),
1425
2.83k
     NULL );
1426
2.83k
  }
1427
2.83k
  return( -1 );
1428
1.58k
}
1429
1430
/* Reads a specific attribute list data MFT entry
1431
 * Returns 1 if successful, 0 if not available or -1 on error
1432
 */
1433
int libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(
1434
     libfsntfs_mft_entry_t *mft_entry,
1435
     libfsntfs_io_handle_t *io_handle,
1436
     libbfio_handle_t *file_io_handle,
1437
     libfdata_vector_t *mft_entry_vector,
1438
     libfcache_cache_t *mft_entry_cache,
1439
     uint64_t file_reference,
1440
     libcerror_error_t **error )
1441
1.59k
{
1442
1.59k
  libfsntfs_mft_attribute_t *data_mft_attribute = NULL;
1443
1.59k
  libfsntfs_mft_attribute_t *mft_attribute      = NULL;
1444
1.59k
  libfsntfs_mft_entry_t *data_mft_entry         = NULL;
1445
1.59k
  static char *function                         = "libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index";
1446
1.59k
  uint64_t attribute_list_data_mft_entry        = 0;
1447
1.59k
  uint64_t base_record_file_reference           = 0;
1448
1.59k
  int attribute_index                           = 0;
1449
1.59k
  int entry_index                               = 0;
1450
1.59k
  int number_of_attributes                      = 0;
1451
1452
1.59k
  if( mft_entry == NULL )
1453
0
  {
1454
0
    libcerror_error_set(
1455
0
     error,
1456
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1457
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1458
0
     "%s: invalid MFT entry.",
1459
0
     function );
1460
1461
0
    return( -1 );
1462
0
  }
1463
1.59k
  attribute_list_data_mft_entry = file_reference & 0xffffffffffffUL;
1464
1465
#if defined( HAVE_DEBUG_OUTPUT )
1466
  if( libcnotify_verbose != 0 )
1467
  {
1468
    libcnotify_printf(
1469
     "%s: reading data file reference: %" PRIu64 "-%" PRIu16 "\n",
1470
     function,
1471
     attribute_list_data_mft_entry,
1472
     (uint16_t) ( file_reference >> 48 ) );
1473
    libcnotify_printf(
1474
     "\n" );
1475
  }
1476
#endif
1477
1.59k
  if( libfdata_vector_get_element_value_by_index(
1478
1.59k
       mft_entry_vector,
1479
1.59k
       (intptr_t *) file_io_handle,
1480
1.59k
       (libfdata_cache_t *) mft_entry_cache,
1481
1.59k
       (int) attribute_list_data_mft_entry,
1482
1.59k
       (intptr_t **) &data_mft_entry,
1483
1.59k
       0,
1484
1.59k
       error ) != 1 )
1485
333
  {
1486
333
    libcerror_error_set(
1487
333
     error,
1488
333
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1489
333
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1490
333
     "%s: unable to retrieve MFT entry: %" PRIu64 ".",
1491
333
     function,
1492
333
     attribute_list_data_mft_entry );
1493
1494
333
    return( -1 );
1495
333
  }
1496
1.26k
  if( data_mft_entry->header == NULL )
1497
41
  {
1498
41
    return( 0 );
1499
41
  }
1500
1.22k
  if( libfsntfs_mft_entry_header_get_base_record_file_reference(
1501
1.22k
       data_mft_entry->header,
1502
1.22k
       &base_record_file_reference,
1503
1.22k
       error ) != 1 )
1504
0
  {
1505
0
    libcerror_error_set(
1506
0
     error,
1507
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1508
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1509
0
     "%s: unable to retrieve base record file reference.",
1510
0
     function );
1511
1512
0
    return( -1 );
1513
0
  }
1514
1.22k
  if( mft_entry->file_reference != base_record_file_reference )
1515
459
  {
1516
459
    return( 0 );
1517
459
  }
1518
764
  if( libfsntfs_mft_entry_read_attributes_data(
1519
764
       data_mft_entry,
1520
764
       io_handle,
1521
764
       data_mft_entry->data,
1522
764
       data_mft_entry->data_size,
1523
764
       error ) != 1 )
1524
15
  {
1525
15
    libcerror_error_set(
1526
15
     error,
1527
15
     LIBCERROR_ERROR_DOMAIN_IO,
1528
15
     LIBCERROR_IO_ERROR_READ_FAILED,
1529
15
     "%s: unable to read attributes.",
1530
15
     function );
1531
1532
15
    return( -1 );
1533
15
  }
1534
749
  if( libcdata_array_get_number_of_entries(
1535
749
       data_mft_entry->attributes_array,
1536
749
       &number_of_attributes,
1537
749
       error ) != 1 )
1538
0
  {
1539
0
    libcerror_error_set(
1540
0
     error,
1541
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1542
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1543
0
     "%s: unable to retrieve number of attributes.",
1544
0
     function );
1545
1546
0
    return( -1 );
1547
0
  }
1548
749
  for( attribute_index = 0;
1549
5.55k
       attribute_index < number_of_attributes;
1550
4.80k
       attribute_index++ )
1551
4.86k
  {
1552
4.86k
    if( libcdata_array_get_entry_by_index(
1553
4.86k
         data_mft_entry->attributes_array,
1554
4.86k
         attribute_index,
1555
4.86k
         (intptr_t **) &mft_attribute,
1556
4.86k
         error ) != 1 )
1557
0
    {
1558
0
      libcerror_error_set(
1559
0
       error,
1560
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1561
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1562
0
       "%s: unable to retrieve attribute: %d from list MFT entry.",
1563
0
       function,
1564
0
       attribute_index );
1565
1566
0
      return( -1 );
1567
0
    }
1568
4.86k
    if( libfsntfs_mft_attribute_clone(
1569
4.86k
         &data_mft_attribute,
1570
4.86k
         mft_attribute,
1571
4.86k
         error ) != 1 )
1572
0
    {
1573
0
      libcerror_error_set(
1574
0
       error,
1575
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1576
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1577
0
       "%s: unable to clone MFT attribute: %d.",
1578
0
       function,
1579
0
       attribute_index );
1580
1581
0
      return( -1 );
1582
0
    }
1583
    /* mft_entry->attributes_array takes over management of data_mft_attribute
1584
     */
1585
4.86k
    if( libcdata_array_append_entry(
1586
4.86k
         mft_entry->attributes_array,
1587
4.86k
         &entry_index,
1588
4.86k
         (intptr_t *) data_mft_attribute,
1589
4.86k
         error ) != 1 )
1590
0
    {
1591
0
      libcerror_error_set(
1592
0
       error,
1593
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1594
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1595
0
       "%s: unable to append MFT attribute to array.",
1596
0
       function );
1597
1598
0
      libfsntfs_mft_attribute_free(
1599
0
       &data_mft_attribute,
1600
0
       NULL );
1601
1602
0
      return( -1 );
1603
0
    }
1604
4.86k
    if( libfsntfs_mft_entry_set_attribute_helper_values(
1605
4.86k
         mft_entry,
1606
4.86k
         entry_index,
1607
4.86k
         data_mft_attribute,
1608
4.86k
         error ) != 1 )
1609
57
    {
1610
57
      libcerror_error_set(
1611
57
       error,
1612
57
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1613
57
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1614
57
       "%s: unable to set helper values for attribute: %d.",
1615
57
       function,
1616
57
       entry_index );
1617
1618
57
      return( -1 );
1619
57
    }
1620
4.80k
    data_mft_attribute = NULL;
1621
4.80k
  }
1622
692
  return( 1 );
1623
749
}
1624
1625
/* Reads the attribute list data MFT entries
1626
 * Returns 1 if successful or -1 on error
1627
 */
1628
int libfsntfs_mft_entry_read_attribute_list_data_mft_entries(
1629
     libfsntfs_mft_entry_t *mft_entry,
1630
     libfsntfs_mft_attribute_list_t *attribute_list,
1631
     libfsntfs_io_handle_t *io_handle,
1632
     libbfio_handle_t *file_io_handle,
1633
     libfdata_vector_t *mft_entry_vector,
1634
     libcerror_error_t **error )
1635
427
{
1636
427
  libfcache_cache_t *mft_entry_cache = NULL;
1637
427
  static char *function              = "libfsntfs_mft_entry_read_attribute_list_data_mft_entries";
1638
427
  uint64_t file_reference            = 0;
1639
427
  int file_reference_index           = 0;
1640
427
  int number_of_file_entries         = 0;
1641
427
  int result                         = 0;
1642
1643
427
  if( mft_entry == NULL )
1644
0
  {
1645
0
    libcerror_error_set(
1646
0
     error,
1647
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1648
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1649
0
     "%s: invalid MFT entry.",
1650
0
     function );
1651
1652
0
    return( -1 );
1653
0
  }
1654
  /* Read the list data MFT entries
1655
   * Use a local cache to prevent cache outs
1656
   */
1657
427
  if( libfcache_cache_initialize(
1658
427
       &mft_entry_cache,
1659
427
       1,
1660
427
       error ) != 1 )
1661
0
  {
1662
0
    libcerror_error_set(
1663
0
     error,
1664
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1665
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1666
0
     "%s: unable to create MFT entry cache.",
1667
0
     function );
1668
1669
0
    goto on_error;
1670
0
  }
1671
427
  if( libfsntfs_mft_attribute_list_get_number_of_file_references(
1672
427
       attribute_list,
1673
427
       &number_of_file_entries,
1674
427
       error ) != 1 )
1675
0
  {
1676
0
    libcerror_error_set(
1677
0
     error,
1678
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1679
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1680
0
     "%s: unable to retrieve number of attribute list data MFT entries.",
1681
0
     function );
1682
1683
0
    goto on_error;
1684
0
  }
1685
427
  for( file_reference_index = 0;
1686
926
       file_reference_index < number_of_file_entries;
1687
499
       file_reference_index++ )
1688
565
  {
1689
565
    if( libfsntfs_mft_attribute_list_get_file_reference_by_index(
1690
565
         attribute_list,
1691
565
         file_reference_index,
1692
565
         &file_reference,
1693
565
         error ) != 1 )
1694
0
    {
1695
0
      libcerror_error_set(
1696
0
       error,
1697
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1698
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1699
0
       "%s: unable to retrieve attribute list data MFT entry: %d.",
1700
0
       function,
1701
0
       file_reference_index );
1702
1703
0
      goto on_error;
1704
0
    }
1705
565
    result = libfsntfs_mft_entry_read_attribute_list_data_mft_entry_by_index(
1706
565
              mft_entry,
1707
565
              io_handle,
1708
565
              file_io_handle,
1709
565
              mft_entry_vector,
1710
565
              mft_entry_cache,
1711
565
              file_reference,
1712
565
              error );
1713
1714
565
    if( result == -1 )
1715
66
    {
1716
66
      libcerror_error_set(
1717
66
       error,
1718
66
       LIBCERROR_ERROR_DOMAIN_IO,
1719
66
       LIBCERROR_IO_ERROR_READ_FAILED,
1720
66
       "%s: unable to read attribute list data MFT entry: %" PRIu64 "-%" PRIu64 ".",
1721
66
       function,
1722
66
       file_reference & 0xffffffffffffUL,
1723
66
       file_reference >> 48 );
1724
1725
66
      goto on_error;
1726
66
    }
1727
499
    else if( result == 0 )
1728
353
    {
1729
353
      mft_entry->is_corrupted = 1;
1730
353
    }
1731
565
  }
1732
361
  if( libfcache_cache_free(
1733
361
       &mft_entry_cache,
1734
361
       error ) != 1 )
1735
0
  {
1736
0
    libcerror_error_set(
1737
0
     error,
1738
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1739
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1740
0
     "%s: unable to free MFT entry cache.",
1741
0
     function );
1742
1743
0
    goto on_error;
1744
0
  }
1745
361
  return( 1 );
1746
1747
66
on_error:
1748
66
  if( mft_entry_cache != NULL )
1749
66
  {
1750
66
    libfcache_cache_free(
1751
66
     &mft_entry_cache,
1752
66
     NULL );
1753
66
  }
1754
66
  return( -1 );
1755
361
}
1756
1757
/* Determines if the MFT entry is empty
1758
 * Returns 1 if empty, 0 if not or -1 on error
1759
 */
1760
int libfsntfs_mft_entry_is_empty(
1761
     libfsntfs_mft_entry_t *mft_entry,
1762
     libcerror_error_t **error )
1763
0
{
1764
0
  static char *function = "libfsntfs_mft_entry_is_empty";
1765
1766
0
  if( mft_entry == NULL )
1767
0
  {
1768
0
    libcerror_error_set(
1769
0
     error,
1770
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1771
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1772
0
     "%s: invalid MFT entry.",
1773
0
     function );
1774
1775
0
    return( -1 );
1776
0
  }
1777
0
  return( (int) mft_entry->is_empty );
1778
0
}
1779
1780
/* Determines if the MFT entry is allocated (in use)
1781
 * Returns 1 if allocated, 0 if not or -1 on error
1782
 */
1783
int libfsntfs_mft_entry_is_allocated(
1784
     libfsntfs_mft_entry_t *mft_entry,
1785
     libcerror_error_t **error )
1786
0
{
1787
0
  static char *function = "libfsntfs_mft_entry_is_allocated";
1788
1789
0
  if( mft_entry == NULL )
1790
0
  {
1791
0
    libcerror_error_set(
1792
0
     error,
1793
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1794
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1795
0
     "%s: invalid MFT entry.",
1796
0
     function );
1797
1798
0
    return( -1 );
1799
0
  }
1800
0
  if( mft_entry->header == NULL )
1801
0
  {
1802
0
    libcerror_error_set(
1803
0
     error,
1804
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1805
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1806
0
     "%s: invalid MFT entry - missing header.",
1807
0
     function );
1808
1809
0
    return( -1 );
1810
0
  }
1811
0
  if( ( mft_entry->header->flags & LIBFSNTFS_MFT_ENTRY_FLAG_IN_USE ) != 0 )
1812
0
  {
1813
0
    return( 1 );
1814
0
  }
1815
0
  return( 0 );
1816
0
}
1817
1818
/* Determines if the MFT entry is corrupted
1819
 * Returns 1 if corrupted, 0 if not or -1 on error
1820
 */
1821
int libfsntfs_mft_entry_is_corrupted(
1822
     libfsntfs_mft_entry_t *mft_entry,
1823
     libcerror_error_t **error )
1824
0
{
1825
0
  static char *function = "libfsntfs_mft_entry_is_corrupted";
1826
1827
0
  if( mft_entry == NULL )
1828
0
  {
1829
0
    libcerror_error_set(
1830
0
     error,
1831
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1832
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1833
0
     "%s: invalid MFT entry.",
1834
0
     function );
1835
1836
0
    return( -1 );
1837
0
  }
1838
0
  return( (int) mft_entry->is_corrupted );
1839
0
}
1840
1841
/* Retrieves the file reference
1842
 * Returns 1 if successful or -1 on error
1843
 */
1844
int libfsntfs_mft_entry_get_file_reference(
1845
     libfsntfs_mft_entry_t *mft_entry,
1846
     uint64_t *file_reference,
1847
     libcerror_error_t **error )
1848
5.78k
{
1849
5.78k
  static char *function = "libfsntfs_mft_entry_get_file_reference";
1850
1851
5.78k
  if( mft_entry == NULL )
1852
0
  {
1853
0
    libcerror_error_set(
1854
0
     error,
1855
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1856
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1857
0
     "%s: invalid MFT entry.",
1858
0
     function );
1859
1860
0
    return( -1 );
1861
0
  }
1862
5.78k
  if( file_reference == NULL )
1863
0
  {
1864
0
    libcerror_error_set(
1865
0
     error,
1866
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1867
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1868
0
     "%s: invalid file reference.",
1869
0
     function );
1870
1871
0
    return( -1 );
1872
0
  }
1873
5.78k
  *file_reference = mft_entry->file_reference;
1874
1875
5.78k
  return( 1 );
1876
5.78k
}
1877
1878
/* Retrieves the base record file reference
1879
 * Returns 1 if successful, 0 if not available or -1 on error
1880
 */
1881
int libfsntfs_mft_entry_get_base_record_file_reference(
1882
     libfsntfs_mft_entry_t *mft_entry,
1883
     uint64_t *file_reference,
1884
     libcerror_error_t **error )
1885
22.5k
{
1886
22.5k
  static char *function = "libfsntfs_mft_entry_get_base_record_file_reference";
1887
1888
22.5k
  if( mft_entry == NULL )
1889
0
  {
1890
0
    libcerror_error_set(
1891
0
     error,
1892
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1893
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1894
0
     "%s: invalid MFT entry.",
1895
0
     function );
1896
1897
0
    return( -1 );
1898
0
  }
1899
22.5k
  if( mft_entry->header == NULL )
1900
1.30k
  {
1901
1.30k
    return( 0 );
1902
1.30k
  }
1903
21.2k
  if( libfsntfs_mft_entry_header_get_base_record_file_reference(
1904
21.2k
       mft_entry->header,
1905
21.2k
       file_reference,
1906
21.2k
       error ) != 1 )
1907
0
  {
1908
0
    libcerror_error_set(
1909
0
     error,
1910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1911
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1912
0
     "%s: unable to retrieve base record file reference.",
1913
0
     function );
1914
1915
0
    return( -1 );
1916
0
  }
1917
21.2k
  return( 1 );
1918
21.2k
}
1919
1920
/* Retrieves the journal sequence number
1921
 * Returns 1 if successful or -1 on error
1922
 */
1923
int libfsntfs_mft_entry_get_journal_sequence_number(
1924
     libfsntfs_mft_entry_t *mft_entry,
1925
     uint64_t *journal_sequence_number,
1926
     libcerror_error_t **error )
1927
0
{
1928
0
  static char *function = "libfsntfs_mft_entry_get_journal_sequence_number";
1929
1930
0
  if( mft_entry == NULL )
1931
0
  {
1932
0
    libcerror_error_set(
1933
0
     error,
1934
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1935
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1936
0
     "%s: invalid MFT entry.",
1937
0
     function );
1938
1939
0
    return( -1 );
1940
0
  }
1941
0
  if( libfsntfs_mft_entry_header_get_journal_sequence_number(
1942
0
       mft_entry->header,
1943
0
       journal_sequence_number,
1944
0
       error ) != 1 )
1945
0
  {
1946
0
    libcerror_error_set(
1947
0
     error,
1948
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1949
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1950
0
     "%s: unable to retrieve journal sequence number.",
1951
0
     function );
1952
1953
0
    return( -1 );
1954
0
  }
1955
0
  return( 1 );
1956
0
}
1957
1958
/* Retrieves the number of attributes
1959
 * Returns 1 if successful or -1 on error
1960
 */
1961
int libfsntfs_mft_entry_get_number_of_attributes(
1962
     libfsntfs_mft_entry_t *mft_entry,
1963
     int *number_of_attributes,
1964
     libcerror_error_t **error )
1965
2.03k
{
1966
2.03k
  static char *function = "libfsntfs_mft_entry_get_number_of_attributes";
1967
1968
2.03k
  if( mft_entry == NULL )
1969
0
  {
1970
0
    libcerror_error_set(
1971
0
     error,
1972
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1973
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1974
0
     "%s: invalid MFT entry.",
1975
0
     function );
1976
1977
0
    return( -1 );
1978
0
  }
1979
2.03k
  if( libcdata_array_get_number_of_entries(
1980
2.03k
       mft_entry->attributes_array,
1981
2.03k
       number_of_attributes,
1982
2.03k
       error ) != 1 )
1983
0
  {
1984
0
    libcerror_error_set(
1985
0
     error,
1986
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1987
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1988
0
     "%s: unable to retrieve number of entries from attributes array.",
1989
0
     function );
1990
1991
0
    return( -1 );
1992
0
  }
1993
2.03k
  return( 1 );
1994
2.03k
}
1995
1996
/* Retrieves a specific attribute
1997
 * Returns 1 if successful or -1 on error
1998
 */
1999
int libfsntfs_mft_entry_get_attribute_by_index(
2000
     libfsntfs_mft_entry_t *mft_entry,
2001
     int attribute_index,
2002
     libfsntfs_mft_attribute_t **attribute,
2003
     libcerror_error_t **error )
2004
14.5k
{
2005
14.5k
  static char *function = "libfsntfs_mft_entry_get_attribute_by_index";
2006
2007
14.5k
  if( mft_entry == NULL )
2008
0
  {
2009
0
    libcerror_error_set(
2010
0
     error,
2011
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2012
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2013
0
     "%s: invalid MFT entry.",
2014
0
     function );
2015
2016
0
    return( -1 );
2017
0
  }
2018
14.5k
  if( libcdata_array_get_entry_by_index(
2019
14.5k
       mft_entry->attributes_array,
2020
14.5k
       attribute_index,
2021
14.5k
       (intptr_t **) attribute,
2022
14.5k
       error ) != 1 )
2023
200
  {
2024
200
    libcerror_error_set(
2025
200
     error,
2026
200
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2027
200
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2028
200
     "%s: unable to retrieve entry: %d from attributes array.",
2029
200
     function,
2030
200
     attribute_index );
2031
2032
200
    return( -1 );
2033
200
  }
2034
14.3k
  return( 1 );
2035
14.5k
}
2036
2037
/* Retrieves the $STANDARD_INFORMATION attribute
2038
 * Returns 1 if successful, 0 if not available or -1 on error
2039
 */
2040
int libfsntfs_mft_entry_get_standard_information_attribute(
2041
     libfsntfs_mft_entry_t *mft_entry,
2042
     libfsntfs_mft_attribute_t **attribute,
2043
     libcerror_error_t **error )
2044
195
{
2045
195
  static char *function = "libfsntfs_mft_entry_get_standard_information_attribute";
2046
2047
195
  if( mft_entry == NULL )
2048
0
  {
2049
0
    libcerror_error_set(
2050
0
     error,
2051
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2052
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2053
0
     "%s: invalid MFT entry.",
2054
0
     function );
2055
2056
0
    return( -1 );
2057
0
  }
2058
195
  if( mft_entry->standard_information_attribute_index == -1 )
2059
59
  {
2060
59
    return( 0 );
2061
59
  }
2062
136
  if( libcdata_array_get_entry_by_index(
2063
136
       mft_entry->attributes_array,
2064
136
       mft_entry->standard_information_attribute_index,
2065
136
       (intptr_t **) attribute,
2066
136
       error ) != 1 )
2067
0
  {
2068
0
    libcerror_error_set(
2069
0
     error,
2070
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2071
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2072
0
     "%s: unable to retrieve entry: %d from attributes array.",
2073
0
     function,
2074
0
     mft_entry->standard_information_attribute_index );
2075
2076
0
    return( -1 );
2077
0
  }
2078
136
  return( 1 );
2079
136
}
2080
2081
/* Retrieves the $VOLUME_INFORMATION attribute
2082
 * Returns 1 if successful, 0 if not available or -1 on error
2083
 */
2084
int libfsntfs_mft_entry_get_volume_information_attribute(
2085
     libfsntfs_mft_entry_t *mft_entry,
2086
     libfsntfs_mft_attribute_t **attribute,
2087
     libcerror_error_t **error )
2088
0
{
2089
0
  static char *function = "libfsntfs_mft_entry_get_volume_information_attribute";
2090
2091
0
  if( mft_entry == NULL )
2092
0
  {
2093
0
    libcerror_error_set(
2094
0
     error,
2095
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2096
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2097
0
     "%s: invalid MFT entry.",
2098
0
     function );
2099
2100
0
    return( -1 );
2101
0
  }
2102
0
  if( mft_entry->volume_information_attribute_index == -1 )
2103
0
  {
2104
0
    return( 0 );
2105
0
  }
2106
0
  if( libcdata_array_get_entry_by_index(
2107
0
       mft_entry->attributes_array,
2108
0
       mft_entry->volume_information_attribute_index,
2109
0
       (intptr_t **) attribute,
2110
0
       error ) != 1 )
2111
0
  {
2112
0
    libcerror_error_set(
2113
0
     error,
2114
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2115
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2116
0
     "%s: unable to retrieve entry: %d from attributes array.",
2117
0
     function,
2118
0
     mft_entry->volume_information_attribute_index );
2119
2120
0
    return( -1 );
2121
0
  }
2122
0
  return( 1 );
2123
0
}
2124
2125
/* Retrieves the $VOLUME_NAME attribute
2126
 * Returns 1 if successful, 0 if not available or -1 on error
2127
 */
2128
int libfsntfs_mft_entry_get_volume_name_attribute(
2129
     libfsntfs_mft_entry_t *mft_entry,
2130
     libfsntfs_mft_attribute_t **attribute,
2131
     libcerror_error_t **error )
2132
0
{
2133
0
  static char *function = "libfsntfs_mft_entry_get_volume_name_attribute";
2134
2135
0
  if( mft_entry == NULL )
2136
0
  {
2137
0
    libcerror_error_set(
2138
0
     error,
2139
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2140
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2141
0
     "%s: invalid MFT entry.",
2142
0
     function );
2143
2144
0
    return( -1 );
2145
0
  }
2146
0
  if( mft_entry->volume_name_attribute_index == -1 )
2147
0
  {
2148
0
    return( 0 );
2149
0
  }
2150
0
  if( libcdata_array_get_entry_by_index(
2151
0
       mft_entry->attributes_array,
2152
0
       mft_entry->volume_name_attribute_index,
2153
0
       (intptr_t **) attribute,
2154
0
       error ) != 1 )
2155
0
  {
2156
0
    libcerror_error_set(
2157
0
     error,
2158
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2159
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2160
0
     "%s: unable to retrieve entry: %d from attributes array.",
2161
0
     function,
2162
0
     mft_entry->volume_name_attribute_index );
2163
2164
0
    return( -1 );
2165
0
  }
2166
0
  return( 1 );
2167
0
}
2168
2169
/* Retrieves the number of alternate data attributes
2170
 * Returns 1 if successful or -1 on error
2171
 */
2172
int libfsntfs_mft_entry_get_number_of_alternate_data_attributes(
2173
     libfsntfs_mft_entry_t *mft_entry,
2174
     int *number_of_attributes,
2175
     libcerror_error_t **error )
2176
0
{
2177
0
  static char *function = "libfsntfs_mft_entry_get_number_of_alternate_data_attributes";
2178
2179
0
  if( mft_entry == NULL )
2180
0
  {
2181
0
    libcerror_error_set(
2182
0
     error,
2183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2184
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2185
0
     "%s: invalid MFT entry.",
2186
0
     function );
2187
2188
0
    return( -1 );
2189
0
  }
2190
0
  if( libcdata_array_get_number_of_entries(
2191
0
       mft_entry->alternate_data_attributes_array,
2192
0
       number_of_attributes,
2193
0
       error ) != 1 )
2194
0
  {
2195
0
    libcerror_error_set(
2196
0
     error,
2197
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2198
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2199
0
     "%s: unable to retrieve number of entries from alternate data attributes array.",
2200
0
     function );
2201
2202
0
    return( -1 );
2203
0
  }
2204
0
  return( 1 );
2205
0
}
2206
2207
/* Retrieves a specific alternate data attribute
2208
 * Returns 1 if successful or -1 on error
2209
 */
2210
int libfsntfs_mft_entry_get_alternate_data_attribute_by_index(
2211
     libfsntfs_mft_entry_t *mft_entry,
2212
     int attribute_index,
2213
     libfsntfs_mft_attribute_t **attribute,
2214
     libcerror_error_t **error )
2215
0
{
2216
0
  static char *function = "libfsntfs_mft_entry_get_alternate_data_attribute_by_index";
2217
2218
0
  if( mft_entry == NULL )
2219
0
  {
2220
0
    libcerror_error_set(
2221
0
     error,
2222
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2223
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2224
0
     "%s: invalid MFT entry.",
2225
0
     function );
2226
2227
0
    return( -1 );
2228
0
  }
2229
0
  if( libcdata_array_get_entry_by_index(
2230
0
       mft_entry->alternate_data_attributes_array,
2231
0
       attribute_index,
2232
0
       (intptr_t **) attribute,
2233
0
       error ) != 1 )
2234
0
  {
2235
0
    libcerror_error_set(
2236
0
     error,
2237
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2238
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2239
0
     "%s: unable to retrieve entry: %d from alternate data attributes array.",
2240
0
     function,
2241
0
     attribute_index );
2242
2243
0
    return( -1 );
2244
0
  }
2245
0
  return( 1 );
2246
0
}
2247
2248
/* Retrieves a specific alternate data attribute for an UTF-8 encoded name
2249
 * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error
2250
 */
2251
int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name(
2252
     libfsntfs_mft_entry_t *mft_entry,
2253
     const uint8_t *utf8_string,
2254
     size_t utf8_string_length,
2255
     libfsntfs_mft_attribute_t **attribute,
2256
     libcerror_error_t **error )
2257
961
{
2258
961
  static char *function    = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf8_name";
2259
961
  int attribute_index      = 0;
2260
961
  int number_of_attributes = 0;
2261
961
  int result               = 0;
2262
2263
961
  if( mft_entry == NULL )
2264
0
  {
2265
0
    libcerror_error_set(
2266
0
     error,
2267
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2268
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2269
0
     "%s: invalid MFT entry.",
2270
0
     function );
2271
2272
0
    return( -1 );
2273
0
  }
2274
961
  if( attribute == NULL )
2275
0
  {
2276
0
    libcerror_error_set(
2277
0
     error,
2278
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2279
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2280
0
     "%s: invalid attribute.",
2281
0
     function );
2282
2283
0
    return( -1 );
2284
0
  }
2285
961
  if( libcdata_array_get_number_of_entries(
2286
961
       mft_entry->alternate_data_attributes_array,
2287
961
       &number_of_attributes,
2288
961
       error ) != 1 )
2289
0
  {
2290
0
    libcerror_error_set(
2291
0
     error,
2292
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2293
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2294
0
     "%s: unable to retrieve number of entries from alternate data attributes array.",
2295
0
     function );
2296
2297
0
    return( -1 );
2298
0
  }
2299
961
  for( attribute_index = 0;
2300
1.09k
       attribute_index < number_of_attributes;
2301
961
       attribute_index++ )
2302
1.08k
  {
2303
1.08k
    if( libcdata_array_get_entry_by_index(
2304
1.08k
         mft_entry->alternate_data_attributes_array,
2305
1.08k
         attribute_index,
2306
1.08k
         (intptr_t **) attribute,
2307
1.08k
         error ) != 1 )
2308
0
    {
2309
0
      libcerror_error_set(
2310
0
       error,
2311
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2312
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2313
0
       "%s: unable to retrieve entry: %d from alternative data attributes array.",
2314
0
       function,
2315
0
       attribute_index );
2316
2317
0
      return( -1 );
2318
0
    }
2319
1.08k
    result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
2320
1.08k
              *attribute,
2321
1.08k
              utf8_string,
2322
1.08k
              utf8_string_length,
2323
1.08k
              error );
2324
2325
1.08k
    if( result == -1 )
2326
0
    {
2327
0
      libcerror_error_set(
2328
0
       error,
2329
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2330
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2331
0
       "%s: unable to compare UTF-8 string with alternative data attribute name.",
2332
0
       function );
2333
2334
0
      goto on_error;
2335
0
    }
2336
1.08k
    else if( result == 1 )
2337
950
    {
2338
950
      return( 1 );
2339
950
    }
2340
1.08k
  }
2341
11
  *attribute = NULL;
2342
2343
11
  return( 0 );
2344
2345
0
on_error:
2346
0
  *attribute = NULL;
2347
2348
0
  return( -1 );
2349
961
}
2350
2351
/* Retrieves a specific alternate data attribute for an UTF-16 encoded name
2352
 * Returns 1 if successful, 0 if no such alternate data attribute or -1 on error
2353
 */
2354
int libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name(
2355
     libfsntfs_mft_entry_t *mft_entry,
2356
     const uint16_t *utf16_string,
2357
     size_t utf16_string_length,
2358
     libfsntfs_mft_attribute_t **attribute,
2359
     libcerror_error_t **error )
2360
0
{
2361
0
  static char *function    = "libfsntfs_mft_entry_get_alternate_data_attribute_by_utf16_name";
2362
0
  int attribute_index      = 0;
2363
0
  int number_of_attributes = 0;
2364
0
  int result               = 0;
2365
2366
0
  if( mft_entry == NULL )
2367
0
  {
2368
0
    libcerror_error_set(
2369
0
     error,
2370
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2371
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2372
0
     "%s: invalid MFT entry.",
2373
0
     function );
2374
2375
0
    return( -1 );
2376
0
  }
2377
0
  if( attribute == NULL )
2378
0
  {
2379
0
    libcerror_error_set(
2380
0
     error,
2381
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2382
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2383
0
     "%s: invalid attribute.",
2384
0
     function );
2385
2386
0
    return( -1 );
2387
0
  }
2388
0
  if( libcdata_array_get_number_of_entries(
2389
0
       mft_entry->alternate_data_attributes_array,
2390
0
       &number_of_attributes,
2391
0
       error ) != 1 )
2392
0
  {
2393
0
    libcerror_error_set(
2394
0
     error,
2395
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2396
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2397
0
     "%s: unable to retrieve number of entries from alternate data attributes array.",
2398
0
     function );
2399
2400
0
    return( -1 );
2401
0
  }
2402
0
  for( attribute_index = 0;
2403
0
       attribute_index < number_of_attributes;
2404
0
       attribute_index++ )
2405
0
  {
2406
0
    if( libcdata_array_get_entry_by_index(
2407
0
         mft_entry->alternate_data_attributes_array,
2408
0
         attribute_index,
2409
0
         (intptr_t **) attribute,
2410
0
         error ) != 1 )
2411
0
    {
2412
0
      libcerror_error_set(
2413
0
       error,
2414
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2415
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2416
0
       "%s: unable to retrieve entry: %d from alternative data attributes array.",
2417
0
       function,
2418
0
       attribute_index );
2419
2420
0
      return( -1 );
2421
0
    }
2422
0
    result = libfsntfs_mft_attribute_compare_name_with_utf16_string(
2423
0
              *attribute,
2424
0
              utf16_string,
2425
0
              utf16_string_length,
2426
0
              error );
2427
2428
0
    if( result == -1 )
2429
0
    {
2430
0
      libcerror_error_set(
2431
0
       error,
2432
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2433
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2434
0
       "%s: unable to compare UTF-16 string with alternative data attribute name.",
2435
0
       function );
2436
2437
0
      goto on_error;
2438
0
    }
2439
0
    else if( result == 1 )
2440
0
    {
2441
0
      return( 1 );
2442
0
    }
2443
0
  }
2444
0
  *attribute = NULL;
2445
2446
0
  return( 0 );
2447
2448
0
on_error:
2449
0
  *attribute = NULL;
2450
2451
0
  return( -1 );
2452
0
}
2453
2454
/* Sets the attribute helper values for an attribute
2455
 * Returns 1 if successful or -1 on error
2456
 */
2457
int libfsntfs_mft_entry_set_attribute_helper_values(
2458
     libfsntfs_mft_entry_t *mft_entry,
2459
     int attribute_index,
2460
     libfsntfs_mft_attribute_t *attribute,
2461
     libcerror_error_t **error )
2462
57.2k
{
2463
57.2k
  uint8_t utf8_attribute_name[ 8 ];
2464
2465
57.2k
  static char *function                                                = "libfsntfs_mft_entry_set_attribute_helper_values";
2466
57.2k
  size_t utf8_attribute_name_size                                      = 0;
2467
57.2k
  uint32_t attribute_type                                              = 0;
2468
57.2k
  int result                                                           = 0;
2469
2470
#if defined( HAVE_DEBUG_OUTPUT )
2471
  libfsntfs_standard_information_values_t *standard_information_values = NULL;
2472
#endif
2473
2474
57.2k
  if( mft_entry == NULL )
2475
0
  {
2476
0
    libcerror_error_set(
2477
0
     error,
2478
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2479
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2480
0
     "%s: invalid MFT entry.",
2481
0
     function );
2482
2483
0
    return( -1 );
2484
0
  }
2485
57.2k
  if( libfsntfs_mft_attribute_get_utf8_name_size(
2486
57.2k
       attribute,
2487
57.2k
       &utf8_attribute_name_size,
2488
57.2k
       error ) != 1 )
2489
100
  {
2490
100
    libcerror_error_set(
2491
100
     error,
2492
100
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2493
100
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2494
100
     "%s: unable to retrieve UTF-8 attribute name size.",
2495
100
     function );
2496
2497
100
    return( -1 );
2498
100
  }
2499
57.1k
  if( libfsntfs_mft_attribute_get_type(
2500
57.1k
       attribute,
2501
57.1k
       &attribute_type,
2502
57.1k
       error ) != 1 )
2503
0
  {
2504
0
    libcerror_error_set(
2505
0
     error,
2506
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2507
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2508
0
     "%s: unable to retrieve attribute type.",
2509
0
     function );
2510
2511
0
    return( -1 );
2512
0
  }
2513
57.1k
  switch( attribute_type )
2514
57.1k
  {
2515
21.5k
    case LIBFSNTFS_ATTRIBUTE_TYPE_DATA:
2516
21.5k
      if( libfsntfs_mft_entry_set_data_attribute_helper_values(
2517
21.5k
           mft_entry,
2518
21.5k
           attribute,
2519
21.5k
           error ) != 1 )
2520
0
      {
2521
0
        libcerror_error_set(
2522
0
         error,
2523
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2524
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2525
0
         "%s: unable to set data attribute helper values.",
2526
0
         function );
2527
2528
0
        return( -1 );
2529
0
      }
2530
21.5k
      break;
2531
2532
21.5k
    case LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME:
2533
7.21k
      if( mft_entry->file_name_attribute_index == -1 )
2534
6.75k
      {
2535
6.75k
        mft_entry->file_name_attribute_index = attribute_index;
2536
6.75k
      }
2537
7.21k
      break;
2538
2539
6.18k
    case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT:
2540
      /* Only interested in attribute names that would match $I30
2541
       */
2542
6.18k
      if( ( utf8_attribute_name_size == 0 )
2543
5.93k
       || ( utf8_attribute_name_size > 8 ) )
2544
562
      {
2545
562
        break;
2546
562
      }
2547
5.62k
      if( libfsntfs_mft_attribute_get_utf8_name(
2548
5.62k
           attribute,
2549
5.62k
           utf8_attribute_name,
2550
5.62k
           utf8_attribute_name_size,
2551
5.62k
           error ) != 1 )
2552
0
      {
2553
0
        libcerror_error_set(
2554
0
         error,
2555
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2556
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2557
0
         "%s: unable to retrieve UTF-8 attribute name.",
2558
0
         function );
2559
2560
0
        return( -1 );
2561
0
      }
2562
5.62k
      result = libuna_utf8_string_compare_with_utf8_stream(
2563
5.62k
                utf8_attribute_name,
2564
5.62k
                utf8_attribute_name_size,
2565
5.62k
                (uint8_t *) "$I30",
2566
5.62k
                4,
2567
5.62k
                error );
2568
2569
5.62k
      if( result == -1 )
2570
0
      {
2571
0
        libcerror_error_set(
2572
0
         error,
2573
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2574
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
2575
0
         "%s: unable to compare UTF-8 string with $I30.",
2576
0
         function );
2577
2578
0
        return( -1 );
2579
0
      }
2580
5.62k
      else if( result == LIBUNA_COMPARE_EQUAL )
2581
2.70k
      {
2582
2.70k
        mft_entry->has_i30_index = 1;
2583
2.70k
      }
2584
5.62k
      break;
2585
2586
5.62k
    case LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT:
2587
      /* Assume only one reparse point attribute per MFT entry is allowed
2588
       */
2589
117
      if( mft_entry->reparse_point_attribute_index != -1 )
2590
21
      {
2591
21
        libcerror_error_set(
2592
21
         error,
2593
21
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2594
21
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2595
21
         "%s: invalid MFT entry - reparse point attribute index value already set.",
2596
21
         function );
2597
2598
21
        return( -1 );
2599
21
      }
2600
96
      mft_entry->reparse_point_attribute_index = attribute_index;
2601
2602
96
      break;
2603
2604
1.32k
    case LIBFSNTFS_ATTRIBUTE_TYPE_SECURITY_DESCRIPTOR:
2605
      /* Assume only one security descriptor attribute per MFT entry is allowed
2606
       */
2607
1.32k
      if( mft_entry->security_descriptor_attribute_index != -1 )
2608
19
      {
2609
19
        libcerror_error_set(
2610
19
         error,
2611
19
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2612
19
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2613
19
         "%s: invalid MFT entry - security descriptor attribute index value already set.",
2614
19
         function );
2615
2616
19
        return( -1 );
2617
19
      }
2618
1.30k
      mft_entry->security_descriptor_attribute_index = attribute_index;
2619
2620
1.30k
      break;
2621
2622
997
    case LIBFSNTFS_ATTRIBUTE_TYPE_STANDARD_INFORMATION:
2623
#if defined( HAVE_DEBUG_OUTPUT )
2624
      if( libfsntfs_standard_information_values_initialize(
2625
           &standard_information_values,
2626
           error ) != 1 )
2627
      {
2628
        libcerror_error_set(
2629
         error,
2630
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2631
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
2632
         "%s: unable to create standard information values.",
2633
         function );
2634
2635
        return( -1 );
2636
      }
2637
      if( libfsntfs_standard_information_values_read_from_mft_attribute(
2638
           standard_information_values,
2639
           attribute,
2640
           error ) != 1 )
2641
      {
2642
        libcerror_error_set(
2643
         error,
2644
         LIBCERROR_ERROR_DOMAIN_IO,
2645
         LIBCERROR_IO_ERROR_READ_FAILED,
2646
         "%s: unable to read standard information values from MFT attribute.",
2647
         function );
2648
2649
        libfsntfs_standard_information_values_free(
2650
         &standard_information_values,
2651
         NULL );
2652
2653
        return( -1 );
2654
      }
2655
      if( libfsntfs_standard_information_values_free(
2656
           &standard_information_values,
2657
           error ) != 1 )
2658
      {
2659
        libcerror_error_set(
2660
         error,
2661
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2662
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
2663
         "%s: unable to free standard information values.",
2664
         function );
2665
2666
        return( -1 );
2667
      }
2668
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
2669
2670
      /* Assume only one standard information attribute per MFT entry is allowed
2671
       */
2672
997
      if( mft_entry->standard_information_attribute_index != -1 )
2673
19
      {
2674
19
        libcerror_error_set(
2675
19
         error,
2676
19
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2677
19
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2678
19
         "%s: invalid MFT entry - standard information attribute index value already set.",
2679
19
         function );
2680
2681
19
        return( -1 );
2682
19
      }
2683
978
      mft_entry->standard_information_attribute_index = attribute_index;
2684
2685
978
      break;
2686
2687
99
    case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_INFORMATION:
2688
      /* Assume only one volume information attribute per MFT entry is allowed
2689
       */
2690
99
      if( mft_entry->volume_information_attribute_index != -1 )
2691
17
      {
2692
17
        libcerror_error_set(
2693
17
         error,
2694
17
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2695
17
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2696
17
         "%s: invalid MFT entry - volume information attribute index value already set.",
2697
17
         function );
2698
2699
17
        return( -1 );
2700
17
      }
2701
82
      mft_entry->volume_information_attribute_index = attribute_index;
2702
2703
82
      break;
2704
2705
76
    case LIBFSNTFS_ATTRIBUTE_TYPE_VOLUME_NAME:
2706
      /* Assume only one volume name attribute per MFT entry is allowed
2707
       */
2708
76
      if( mft_entry->volume_name_attribute_index != -1 )
2709
18
      {
2710
18
        libcerror_error_set(
2711
18
         error,
2712
18
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2713
18
         LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
2714
18
         "%s: invalid MFT entry - volume name attribute index value already set.",
2715
18
         function );
2716
2717
18
        return( -1 );
2718
18
      }
2719
58
      mft_entry->volume_name_attribute_index = attribute_index;
2720
2721
58
      break;
2722
2723
19.6k
    default:
2724
19.6k
      break;
2725
57.1k
  }
2726
57.0k
  return( 1 );
2727
57.1k
}
2728
2729
/* Sets the attribute helper values for a $DATA attribute
2730
 * Returns 1 if successful or -1 on error
2731
 */
2732
int libfsntfs_mft_entry_set_data_attribute_helper_values(
2733
     libfsntfs_mft_entry_t *mft_entry,
2734
     libfsntfs_mft_attribute_t *data_attribute,
2735
     libcerror_error_t **error )
2736
21.5k
{
2737
21.5k
  libfsntfs_mft_attribute_t *existing_data_attribute = NULL;
2738
21.5k
  uint8_t *utf8_attribute_name                       = NULL;
2739
21.5k
  static char *function                              = "libfsntfs_mft_entry_set_data_attribute_helper_values";
2740
21.5k
  size_t utf8_attribute_name_size                    = 0;
2741
21.5k
  int attribute_index                                = 0;
2742
21.5k
  int entry_index                                    = 0;
2743
21.5k
  int result                                         = 0;
2744
2745
21.5k
  if( mft_entry == NULL )
2746
0
  {
2747
0
    libcerror_error_set(
2748
0
     error,
2749
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2750
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2751
0
     "%s: invalid MFT entry.",
2752
0
     function );
2753
2754
0
    return( -1 );
2755
0
  }
2756
21.5k
  if( libfsntfs_mft_attribute_get_utf8_name_size(
2757
21.5k
       data_attribute,
2758
21.5k
       &utf8_attribute_name_size,
2759
21.5k
       error ) != 1 )
2760
0
  {
2761
0
    libcerror_error_set(
2762
0
     error,
2763
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
2764
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2765
0
     "%s: unable to retrieve UTF-8 attribute name size.",
2766
0
     function );
2767
2768
0
    goto on_error;
2769
0
  }
2770
21.5k
  if( utf8_attribute_name_size <= 1 )
2771
14.3k
  {
2772
14.3k
    if( libfsntfs_mft_attribute_append_to_chain(
2773
14.3k
         &( mft_entry->data_attribute ),
2774
14.3k
         data_attribute,
2775
14.3k
         error ) != 1 )
2776
0
    {
2777
0
      libcerror_error_set(
2778
0
       error,
2779
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2780
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2781
0
       "%s: unable to chain attribute.",
2782
0
       function );
2783
2784
0
      goto on_error;
2785
0
    }
2786
14.3k
  }
2787
7.18k
  else
2788
7.18k
  {
2789
7.18k
    if( utf8_attribute_name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
2790
0
    {
2791
0
      libcerror_error_set(
2792
0
       error,
2793
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2794
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
2795
0
       "%s: invalid UTF-8 attribute name size value out of bounds.",
2796
0
       function );
2797
2798
0
      goto on_error;
2799
0
    }
2800
7.18k
    utf8_attribute_name = (uint8_t *) memory_allocate(
2801
7.18k
                                       (size_t) utf8_attribute_name_size );
2802
2803
7.18k
    if( utf8_attribute_name == NULL )
2804
0
    {
2805
0
      libcerror_error_set(
2806
0
       error,
2807
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
2808
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
2809
0
       "%s: unable to create UTF-8 attribute name.",
2810
0
       function );
2811
2812
0
      goto on_error;
2813
0
    }
2814
7.18k
    if( libfsntfs_mft_attribute_get_utf8_name(
2815
7.18k
         data_attribute,
2816
7.18k
         utf8_attribute_name,
2817
7.18k
         utf8_attribute_name_size,
2818
7.18k
         error ) != 1 )
2819
0
    {
2820
0
      libcerror_error_set(
2821
0
       error,
2822
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2823
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2824
0
       "%s: unable to retrieve UTF-8 attribute name.",
2825
0
       function );
2826
2827
0
      goto on_error;
2828
0
    }
2829
7.18k
    result = libfsntfs_mft_entry_get_data_attribute_by_utf8_name(
2830
7.18k
              mft_entry,
2831
7.18k
              utf8_attribute_name,
2832
7.18k
              utf8_attribute_name_size,
2833
7.18k
              &attribute_index,
2834
7.18k
              &existing_data_attribute,
2835
7.18k
              error );
2836
2837
7.18k
    if( result == -1 )
2838
0
    {
2839
0
      libcerror_error_set(
2840
0
       error,
2841
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2842
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
2843
0
       "%s: unable to retrieve data attribute.",
2844
0
       function );
2845
2846
0
      goto on_error;
2847
0
    }
2848
7.18k
    else if( result == 0 )
2849
5.19k
    {
2850
5.19k
      if( libcdata_array_append_entry(
2851
5.19k
           mft_entry->alternate_data_attributes_array,
2852
5.19k
           &entry_index,
2853
5.19k
           (intptr_t *) data_attribute,
2854
5.19k
           error ) != 1 )
2855
0
      {
2856
0
        libcerror_error_set(
2857
0
         error,
2858
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2859
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2860
0
         "%s: unable to append alternate data attribute to array.",
2861
0
         function );
2862
2863
0
        goto on_error;
2864
0
      }
2865
5.19k
      existing_data_attribute = data_attribute;
2866
5.19k
    }
2867
1.98k
    else
2868
1.98k
    {
2869
1.98k
      if( libfsntfs_mft_attribute_append_to_chain(
2870
1.98k
           &existing_data_attribute,
2871
1.98k
           data_attribute,
2872
1.98k
           error ) != 1 )
2873
0
      {
2874
0
        libcerror_error_set(
2875
0
         error,
2876
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2877
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
2878
0
         "%s: unable to chain alternate data attribute.",
2879
0
         function );
2880
2881
0
        goto on_error;
2882
0
      }
2883
1.98k
      if( libcdata_array_set_entry_by_index(
2884
1.98k
           mft_entry->alternate_data_attributes_array,
2885
1.98k
           attribute_index,
2886
1.98k
           (intptr_t *) existing_data_attribute,
2887
1.98k
           error ) != 1 )
2888
0
      {
2889
0
        libcerror_error_set(
2890
0
         error,
2891
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
2892
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
2893
0
         "%s: unable to append set data attribute: %d in array.",
2894
0
         function,
2895
0
         attribute_index );
2896
2897
0
        goto on_error;
2898
0
      }
2899
1.98k
    }
2900
7.18k
    memory_free(
2901
7.18k
     utf8_attribute_name );
2902
2903
7.18k
    utf8_attribute_name = NULL;
2904
2905
7.18k
    result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
2906
7.18k
              data_attribute,
2907
7.18k
              (uint8_t *) "WofCompressedData",
2908
7.18k
              17,
2909
7.18k
              error );
2910
2911
7.18k
    if( result == -1 )
2912
0
    {
2913
0
      libcerror_error_set(
2914
0
       error,
2915
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
2916
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
2917
0
       "%s: unable to compare UTF-8 string with alternative data attribute name.",
2918
0
       function );
2919
2920
0
      goto on_error;
2921
0
    }
2922
7.18k
    else if( result == 1 )
2923
42
    {
2924
42
      mft_entry->wof_compressed_data_attribute = existing_data_attribute;
2925
42
    }
2926
7.18k
  }
2927
21.5k
  return( 1 );
2928
2929
0
on_error:
2930
0
  if( utf8_attribute_name != NULL )
2931
0
  {
2932
0
    memory_free(
2933
0
     utf8_attribute_name );
2934
0
  }
2935
0
  return( -1 );
2936
21.5k
}
2937
2938
/* Retrieves a data attribute with the specified name
2939
 * Returns 1 if successful, 0 if no attribute was found or -1 on error
2940
 */
2941
int libfsntfs_mft_entry_get_data_attribute_by_utf8_name(
2942
     libfsntfs_mft_entry_t *mft_entry,
2943
     const uint8_t *utf8_string,
2944
     size_t utf8_string_length,
2945
     int *attribute_index,
2946
     libfsntfs_mft_attribute_t **attribute,
2947
     libcerror_error_t **error )
2948
7.18k
{
2949
7.18k
  libfsntfs_mft_attribute_t *safe_attribute = NULL;
2950
7.18k
  static char *function                     = "libfsntfs_mft_entry_get_data_attribute_by_utf8_name";
2951
7.18k
  int number_of_attributes                  = 0;
2952
7.18k
  int result                                = 0;
2953
7.18k
  int safe_attribute_index                  = 0;
2954
2955
7.18k
  if( mft_entry == NULL )
2956
0
  {
2957
0
    libcerror_error_set(
2958
0
     error,
2959
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2960
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2961
0
     "%s: invalid MFT entry.",
2962
0
     function );
2963
2964
0
    return( -1 );
2965
0
  }
2966
7.18k
  if( utf8_string == NULL )
2967
0
  {
2968
0
    libcerror_error_set(
2969
0
     error,
2970
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2971
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2972
0
     "%s: invalid UTF-8 string.",
2973
0
     function );
2974
2975
0
    return( -1 );
2976
0
  }
2977
7.18k
  if( utf8_string_length > (size_t) ( SSIZE_MAX - 1 ) )
2978
0
  {
2979
0
    libcerror_error_set(
2980
0
     error,
2981
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2982
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
2983
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
2984
0
     function );
2985
2986
0
    return( -1 );
2987
0
  }
2988
7.18k
  if( attribute_index == NULL )
2989
0
  {
2990
0
    libcerror_error_set(
2991
0
     error,
2992
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
2993
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
2994
0
     "%s: invalid attribute index.",
2995
0
     function );
2996
2997
0
    return( -1 );
2998
0
  }
2999
7.18k
  if( attribute == NULL )
3000
0
  {
3001
0
    libcerror_error_set(
3002
0
     error,
3003
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3004
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3005
0
     "%s: invalid attribute.",
3006
0
     function );
3007
3008
0
    return( -1 );
3009
0
  }
3010
7.18k
  if( libcdata_array_get_number_of_entries(
3011
7.18k
       mft_entry->alternate_data_attributes_array,
3012
7.18k
       &number_of_attributes,
3013
7.18k
       error ) != 1 )
3014
0
  {
3015
0
    libcerror_error_set(
3016
0
     error,
3017
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3018
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3019
0
     "%s: unable to retrieve number of alternate data attributes.",
3020
0
     function );
3021
3022
0
    return( -1 );
3023
0
  }
3024
7.18k
  for( safe_attribute_index = 0;
3025
24.9k
       safe_attribute_index < number_of_attributes;
3026
17.7k
       safe_attribute_index++ )
3027
19.7k
  {
3028
19.7k
    if( libcdata_array_get_entry_by_index(
3029
19.7k
         mft_entry->alternate_data_attributes_array,
3030
19.7k
         safe_attribute_index,
3031
19.7k
         (intptr_t **) &safe_attribute,
3032
19.7k
         error ) != 1 )
3033
0
    {
3034
0
      libcerror_error_set(
3035
0
       error,
3036
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3037
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
3038
0
       "%s: unable to retrieve alternate data attribute: %d.",
3039
0
       function,
3040
0
       safe_attribute_index );
3041
3042
0
      return( -1 );
3043
0
    }
3044
19.7k
    result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
3045
19.7k
              safe_attribute,
3046
19.7k
              utf8_string,
3047
19.7k
              utf8_string_length,
3048
19.7k
              error );
3049
3050
19.7k
    if( result == -1 )
3051
0
    {
3052
0
      libcerror_error_set(
3053
0
       error,
3054
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
3055
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
3056
0
       "%s: unable to compare UTF-8 string with alternative data attribute: %d name.",
3057
0
       function,
3058
0
       safe_attribute_index );
3059
3060
0
      return( -1 );
3061
0
    }
3062
19.7k
    else if( result != 0 )
3063
1.98k
    {
3064
1.98k
      break;
3065
1.98k
    }
3066
19.7k
  }
3067
7.18k
  if( result != 0 )
3068
1.98k
  {
3069
1.98k
    *attribute_index = safe_attribute_index;
3070
1.98k
    *attribute       = safe_attribute;
3071
1.98k
  }
3072
5.19k
  else
3073
5.19k
  {
3074
5.19k
    *attribute_index = 0;
3075
5.19k
    *attribute       = NULL;
3076
5.19k
  }
3077
7.18k
  return( result );
3078
7.18k
}
3079
3080
/* Determines if the file entry has the directory entries ($I30) index
3081
 * Returns 1 if the default data stream, 0 if not or -1 on error
3082
 */
3083
int libfsntfs_mft_entry_has_directory_entries_index(
3084
     libfsntfs_mft_entry_t *mft_entry,
3085
     libcerror_error_t **error )
3086
0
{
3087
0
  static char *function = "libfsntfs_mft_entry_has_directory_entries_index";
3088
3089
0
  if( mft_entry == NULL )
3090
0
  {
3091
0
    libcerror_error_set(
3092
0
     error,
3093
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
3094
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
3095
0
     "%s: invalid MFT entry.",
3096
0
     function );
3097
3098
0
    return( -1 );
3099
0
  }
3100
0
  return( (int) mft_entry->has_i30_index );
3101
0
}
3102
3103
/* Reads the MFT entry
3104
 * Callback function for the MFT entry vector
3105
 * Returns 1 if successful or -1 on error
3106
 */
3107
int libfsntfs_mft_entry_read_element_data(
3108
     intptr_t *data_handle LIBFSNTFS_ATTRIBUTE_UNUSED,
3109
     libbfio_handle_t *file_io_handle,
3110
     libfdata_vector_t *vector,
3111
     libfdata_cache_t *cache,
3112
     int element_index,
3113
     int element_data_file_index LIBFSNTFS_ATTRIBUTE_UNUSED,
3114
     off64_t element_data_offset,
3115
     size64_t element_data_size,
3116
     uint32_t element_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
3117
     uint8_t read_flags LIBFSNTFS_ATTRIBUTE_UNUSED,
3118
     libcerror_error_t **error )
3119
27.0k
{
3120
27.0k
  libfsntfs_mft_entry_t *mft_entry = NULL;
3121
27.0k
  static char *function            = "libfsntfs_mft_entry_read_element_data";
3122
3123
27.0k
  LIBFSNTFS_UNREFERENCED_PARAMETER( data_handle )
3124
27.0k
  LIBFSNTFS_UNREFERENCED_PARAMETER( element_data_file_index )
3125
27.0k
  LIBFSNTFS_UNREFERENCED_PARAMETER( element_flags )
3126
27.0k
  LIBFSNTFS_UNREFERENCED_PARAMETER( read_flags )
3127
3128
27.0k
#if ( SIZEOF_INT <= 4 )
3129
27.0k
  if( element_index < 0 )
3130
#else
3131
  if( ( element_index < 0 )
3132
   || ( (int64_t) element_index > (int64_t) UINT32_MAX ) )
3133
#endif
3134
0
  {
3135
0
    libcerror_error_set(
3136
0
     error,
3137
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3138
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3139
0
     "%s: invalid element index value out of bounds.",
3140
0
     function );
3141
3142
0
    return( -1 );
3143
0
  }
3144
27.0k
  if( element_data_size > (size64_t) UINT32_MAX )
3145
0
  {
3146
0
    libcerror_error_set(
3147
0
     error,
3148
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3149
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
3150
0
     "%s: invalid element data size value out of bounds.",
3151
0
     function );
3152
3153
0
    return( -1 );
3154
0
  }
3155
27.0k
  if( libfsntfs_mft_entry_initialize(
3156
27.0k
       &mft_entry,
3157
27.0k
       error ) != 1 )
3158
0
  {
3159
0
    libcerror_error_set(
3160
0
     error,
3161
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3162
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
3163
0
     "%s: unable to create MFT entry.",
3164
0
     function );
3165
3166
0
    goto on_error;
3167
0
  }
3168
27.0k
  if( libfsntfs_mft_entry_read_file_io_handle(
3169
27.0k
       mft_entry,
3170
27.0k
       file_io_handle,
3171
27.0k
       element_data_offset,
3172
27.0k
       (uint32_t) element_data_size,
3173
27.0k
       (uint32_t) element_index,
3174
27.0k
       error ) != 1 )
3175
331
  {
3176
331
    libcerror_error_set(
3177
331
     error,
3178
331
     LIBCERROR_ERROR_DOMAIN_IO,
3179
331
     LIBCERROR_IO_ERROR_READ_FAILED,
3180
331
     "%s: unable to read MFT entry: %d.",
3181
331
     function,
3182
331
     element_index );
3183
3184
331
    goto on_error;
3185
331
  }
3186
26.7k
  if( libfdata_vector_set_element_value_by_index(
3187
26.7k
       vector,
3188
26.7k
       (intptr_t *) file_io_handle,
3189
26.7k
       cache,
3190
26.7k
       element_index,
3191
26.7k
       (intptr_t *) mft_entry,
3192
26.7k
       (int (*)(intptr_t **, libcerror_error_t **)) &libfsntfs_mft_entry_free,
3193
26.7k
       LIBFDATA_VECTOR_ELEMENT_VALUE_FLAG_MANAGED,
3194
26.7k
       error ) != 1 )
3195
0
  {
3196
0
    libcerror_error_set(
3197
0
     error,
3198
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
3199
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
3200
0
     "%s: unable to set MFT entry as element value.",
3201
0
     function );
3202
3203
0
    goto on_error;
3204
0
  }
3205
26.7k
  return( 1 );
3206
3207
331
on_error:
3208
331
  if( mft_entry != NULL )
3209
331
  {
3210
331
    libfsntfs_mft_entry_free(
3211
331
     &mft_entry,
3212
     NULL );
3213
331
  }
3214
331
  return( -1 );
3215
26.7k
}
3216