Coverage Report

Created: 2025-06-13 07:22

/src/libfsntfs/libfsntfs/libfsntfs_index.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Index 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_bitmap_values.h"
28
#include "libfsntfs_debug.h"
29
#include "libfsntfs_definitions.h"
30
#include "libfsntfs_index.h"
31
#include "libfsntfs_index_entry.h"
32
#include "libfsntfs_index_entry_vector.h"
33
#include "libfsntfs_index_node.h"
34
#include "libfsntfs_index_root_header.h"
35
#include "libfsntfs_index_value.h"
36
#include "libfsntfs_io_handle.h"
37
#include "libfsntfs_libbfio.h"
38
#include "libfsntfs_libcerror.h"
39
#include "libfsntfs_libcnotify.h"
40
#include "libfsntfs_libfcache.h"
41
#include "libfsntfs_libfdata.h"
42
#include "libfsntfs_libuna.h"
43
#include "libfsntfs_mft_attribute.h"
44
#include "libfsntfs_mft_entry.h"
45
#include "libfsntfs_unused.h"
46
47
#include "fsntfs_index.h"
48
49
/* Creates an index
50
 * Make sure the value index is referencing, is set to NULL
51
 * Returns 1 if successful or -1 on error
52
 */
53
int libfsntfs_index_initialize(
54
     libfsntfs_index_t **index,
55
     libfsntfs_io_handle_t *io_handle,
56
     const uint8_t *name,
57
     size_t name_size,
58
     libcerror_error_t **error )
59
2.00k
{
60
2.00k
  static char *function = "libfsntfs_index_initialize";
61
62
2.00k
  if( index == NULL )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
67
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
68
0
     "%s: invalid index.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
2.00k
  if( *index != NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
78
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
79
0
     "%s: invalid index value already set.",
80
0
     function );
81
82
0
    return( -1 );
83
0
  }
84
2.00k
  if( io_handle == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
89
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
90
0
     "%s: invalid IO handle.",
91
0
     function );
92
93
0
    return( -1 );
94
0
  }
95
2.00k
  if( name == NULL )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
100
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
101
0
     "%s: invalid name.",
102
0
     function );
103
104
0
    return( -1 );
105
0
  }
106
2.00k
  if( ( name_size <= 1 )
107
2.00k
   || ( name_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
108
0
  {
109
0
    libcerror_error_set(
110
0
     error,
111
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
112
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
113
0
     "%s: invalid name size value out of bounds.",
114
0
     function );
115
116
0
    return( -1 );
117
0
  }
118
2.00k
  *index = memory_allocate_structure(
119
2.00k
            libfsntfs_index_t );
120
121
2.00k
  if( *index == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
126
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
127
0
     "%s: unable to create index.",
128
0
     function );
129
130
0
    goto on_error;
131
0
  }
132
2.00k
  if( memory_set(
133
2.00k
       *index,
134
2.00k
       0,
135
2.00k
       sizeof( libfsntfs_index_t ) ) == NULL )
136
0
  {
137
0
    libcerror_error_set(
138
0
     error,
139
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
140
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
141
0
     "%s: unable to clear index.",
142
0
     function );
143
144
0
    memory_free(
145
0
     *index );
146
147
0
    *index = NULL;
148
149
0
    return( -1 );
150
0
  }
151
2.00k
  ( *index )->name = (uint8_t *) memory_allocate(
152
2.00k
                                  sizeof( uint8_t ) * name_size );
153
154
2.00k
  if( ( *index )->name == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
159
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
160
0
     "%s: unable to create name.",
161
0
     function );
162
163
0
    goto on_error;
164
0
  }
165
2.00k
  if( memory_copy(
166
2.00k
       ( *index )->name,
167
2.00k
       name,
168
2.00k
       sizeof( uint8_t ) * name_size ) == NULL )
169
0
  {
170
0
    libcerror_error_set(
171
0
     error,
172
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
173
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
174
0
     "%s: unable to copy name.",
175
0
     function );
176
177
0
    goto on_error;
178
0
  }
179
2.00k
  ( *index )->name_size = name_size;
180
2.00k
  ( *index )->io_handle = io_handle;
181
182
2.00k
  return( 1 );
183
184
0
on_error:
185
0
  if( *index != NULL )
186
0
  {
187
0
    if( ( *index )->name != NULL )
188
0
    {
189
0
      memory_free(
190
0
       ( *index )->name );
191
0
    }
192
0
    memory_free(
193
0
     *index );
194
195
0
    *index = NULL;
196
0
  }
197
0
  return( -1 );
198
2.00k
}
199
200
/* Frees an index
201
 * Returns 1 if successful or -1 on error
202
 */
203
int libfsntfs_index_free(
204
     libfsntfs_index_t **index,
205
     libcerror_error_t **error )
206
2.00k
{
207
2.00k
  static char *function = "libfsntfs_index_free";
208
2.00k
  int result            = 1;
209
210
2.00k
  if( index == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
216
0
     "%s: invalid index.",
217
0
     function );
218
219
0
    return( -1 );
220
0
  }
221
2.00k
  if( *index != NULL )
222
2.00k
  {
223
    /* The io_handle, index_root_attribute, index_allocation_attribute and bitmap_attribute references are freed elsewhere
224
     */
225
2.00k
    if( ( *index )->root_header != NULL )
226
1.86k
    {
227
1.86k
      if( libfsntfs_index_root_header_free(
228
1.86k
           &( ( *index )->root_header ),
229
1.86k
           error ) != 1 )
230
0
      {
231
0
        libcerror_error_set(
232
0
         error,
233
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
234
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
235
0
         "%s: unable to free root header.",
236
0
         function );
237
238
0
        result = -1;
239
0
      }
240
1.86k
    }
241
2.00k
    if( ( *index )->root_node != NULL )
242
896
    {
243
896
      if( libfsntfs_index_node_free(
244
896
           &( ( *index )->root_node ),
245
896
           error ) != 1 )
246
0
      {
247
0
        libcerror_error_set(
248
0
         error,
249
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
251
0
         "%s: unable to free root node.",
252
0
         function );
253
254
0
        result = -1;
255
0
      }
256
896
    }
257
2.00k
    if( ( *index )->index_entry_vector != NULL )
258
158
    {
259
158
      if( libfdata_vector_free(
260
158
           &( ( *index )->index_entry_vector ),
261
158
           error ) != 1 )
262
0
      {
263
0
        libcerror_error_set(
264
0
         error,
265
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
266
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
267
0
         "%s: unable to free index entry vector.",
268
0
         function );
269
270
0
        result = -1;
271
0
      }
272
158
    }
273
2.00k
    if( ( *index )->index_node_cache != NULL )
274
158
    {
275
158
      if( libfcache_cache_free(
276
158
           &( ( *index )->index_node_cache ),
277
158
           error ) != 1 )
278
0
      {
279
0
        libcerror_error_set(
280
0
         error,
281
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
282
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
283
0
         "%s: unable to free index node cache.",
284
0
         function );
285
286
0
        result = -1;
287
0
      }
288
158
    }
289
2.00k
    if( ( *index )->bitmap_values != NULL )
290
391
    {
291
391
      if( libfsntfs_bitmap_values_free(
292
391
           &( ( *index )->bitmap_values ),
293
391
           error ) != 1 )
294
0
      {
295
0
        libcerror_error_set(
296
0
         error,
297
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
298
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
299
0
         "%s: unable to free bitmap values.",
300
0
         function );
301
302
0
        result = -1;
303
0
      }
304
391
    }
305
2.00k
    if( ( *index )->name != NULL )
306
2.00k
    {
307
2.00k
      memory_free(
308
2.00k
       ( *index )->name );
309
2.00k
    }
310
2.00k
    memory_free(
311
2.00k
     *index );
312
313
2.00k
    *index = NULL;
314
2.00k
  }
315
2.00k
  return( result );
316
2.00k
}
317
318
/* Reads the index
319
 * Returns 1 if successful, 0 if not available or -1 on error
320
 */
321
int libfsntfs_index_read(
322
     libfsntfs_index_t *index,
323
     libbfio_handle_t *file_io_handle,
324
     libfsntfs_mft_entry_t *mft_entry,
325
     uint8_t flags,
326
     libcerror_error_t **error )
327
2.00k
{
328
2.00k
  libfsntfs_mft_attribute_t *bitmap_attribute           = NULL;
329
2.00k
  libfsntfs_mft_attribute_t *index_allocation_attribute = NULL;
330
2.00k
  libfsntfs_mft_attribute_t *index_root_attribute       = NULL;
331
2.00k
  libfsntfs_mft_attribute_t *mft_attribute              = NULL;
332
2.00k
  static char *function                                 = "libfsntfs_index_read";
333
2.00k
  uint32_t attribute_type                               = 0;
334
2.00k
  uint32_t index_entry_size                             = 0;
335
2.00k
  int attribute_index                                   = 0;
336
2.00k
  int number_of_attributes                              = 0;
337
2.00k
  int result                                            = 0;
338
339
2.00k
  if( index == NULL )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
344
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
345
0
     "%s: invalid index.",
346
0
     function );
347
348
0
    return( -1 );
349
0
  }
350
2.00k
  if( index->io_handle == NULL )
351
0
  {
352
0
    libcerror_error_set(
353
0
     error,
354
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
355
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
356
0
     "%s: invalid index - missing IO handle.",
357
0
     function );
358
359
0
    return( -1 );
360
0
  }
361
2.00k
  if( libfsntfs_mft_entry_get_number_of_attributes(
362
2.00k
       mft_entry,
363
2.00k
       &number_of_attributes,
364
2.00k
       error ) != 1 )
365
0
  {
366
0
    libcerror_error_set(
367
0
     error,
368
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
369
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
370
0
     "%s: unable to retrieve number of attributes.",
371
0
     function );
372
373
0
    return( -1 );
374
0
  }
375
2.00k
  for( attribute_index = 0;
376
13.3k
       attribute_index < number_of_attributes;
377
11.3k
       attribute_index++ )
378
11.3k
  {
379
11.3k
    if( libfsntfs_mft_entry_get_attribute_by_index(
380
11.3k
         mft_entry,
381
11.3k
         attribute_index,
382
11.3k
         &mft_attribute,
383
11.3k
         error ) != 1 )
384
0
    {
385
0
      libcerror_error_set(
386
0
       error,
387
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
388
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
389
0
       "%s: unable to retrieve MFT attribute: %d.",
390
0
       function,
391
0
       attribute_index );
392
393
0
      return( -1 );
394
0
    }
395
11.3k
    result = libfsntfs_mft_attribute_compare_name_with_utf8_string(
396
11.3k
              mft_attribute,
397
11.3k
              index->name,
398
11.3k
              index->name_size,
399
11.3k
              error );
400
401
11.3k
    if( result == -1 )
402
0
    {
403
0
      libcerror_error_set(
404
0
       error,
405
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
407
0
       "%s: unable to compare UTF-8 string with attribute: %d name.",
408
0
       function,
409
0
       attribute_index );
410
411
0
      return( -1 );
412
0
    }
413
11.3k
    else if( result != 0 )
414
3.91k
    {
415
3.91k
      if( libfsntfs_mft_attribute_get_type(
416
3.91k
           mft_attribute,
417
3.91k
           &attribute_type,
418
3.91k
           error ) != 1 )
419
0
      {
420
0
        libcerror_error_set(
421
0
         error,
422
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
423
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
424
0
         "%s: unable to retrieve attribute type.",
425
0
         function );
426
427
0
        return( -1 );
428
0
      }
429
3.91k
      switch( attribute_type )
430
3.91k
      {
431
1.14k
        case LIBFSNTFS_ATTRIBUTE_TYPE_BITMAP:
432
1.14k
          if( libfsntfs_mft_attribute_append_to_chain(
433
1.14k
               &bitmap_attribute,
434
1.14k
               mft_attribute,
435
1.14k
               error ) != 1 )
436
0
          {
437
0
            libcerror_error_set(
438
0
             error,
439
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
0
             LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
441
0
             "%s: unable to append attribute to bitmap attribute chain.",
442
0
             function );
443
444
0
            return( -1 );
445
0
          }
446
1.14k
          break;
447
448
1.14k
        case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ALLOCATION:
449
729
          if( libfsntfs_mft_attribute_append_to_chain(
450
729
               &index_allocation_attribute,
451
729
               mft_attribute,
452
729
               error ) != 1 )
453
0
          {
454
0
            libcerror_error_set(
455
0
             error,
456
0
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
457
0
             LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
458
0
             "%s: unable to append attribute to index allocation attribute chain.",
459
0
             function );
460
461
0
            return( -1 );
462
0
          }
463
729
          break;
464
465
1.90k
        case LIBFSNTFS_ATTRIBUTE_TYPE_INDEX_ROOT:
466
1.90k
          index_root_attribute = mft_attribute;
467
1.90k
          break;
468
469
139
        default:
470
#if defined( HAVE_DEBUG_OUTPUT )
471
          if( libcnotify_verbose != 0 )
472
          {
473
            libcnotify_printf(
474
             "%s: unsupported index attribute type: 0x%08" PRIx32 "\n",
475
             function,
476
             attribute_type );
477
          }
478
#endif
479
139
          break;
480
3.91k
      }
481
3.91k
    }
482
11.3k
  }
483
2.00k
  if( index_root_attribute == NULL )
484
135
  {
485
135
    return( 0 );
486
135
  }
487
1.87k
  if( libfsntfs_index_read_root_header(
488
1.87k
       index,
489
1.87k
       index_root_attribute,
490
1.87k
       error ) != 1 )
491
9
  {
492
9
    libcerror_error_set(
493
9
     error,
494
9
     LIBCERROR_ERROR_DOMAIN_IO,
495
9
     LIBCERROR_IO_ERROR_READ_FAILED,
496
9
     "%s: unable to read index root header.",
497
9
     function );
498
499
9
    goto on_error;
500
9
  }
501
  /* The index does not necessarily have a $BITMAP attribute
502
   */
503
1.86k
  if( bitmap_attribute != NULL )
504
994
  {
505
994
    if( libfsntfs_index_read_bitmap(
506
994
         index,
507
994
         file_io_handle,
508
994
         bitmap_attribute,
509
994
         flags,
510
994
         error ) != 1 )
511
603
    {
512
603
      libcerror_error_set(
513
603
       error,
514
603
       LIBCERROR_ERROR_DOMAIN_IO,
515
603
       LIBCERROR_IO_ERROR_READ_FAILED,
516
603
       "%s: unable to read index bitmap.",
517
603
       function );
518
519
603
      goto on_error;
520
603
    }
521
994
  }
522
1.26k
  if( libfsntfs_index_read_root_node(
523
1.26k
       index,
524
1.26k
       index_root_attribute,
525
1.26k
       error ) != 1 )
526
362
  {
527
362
    libcerror_error_set(
528
362
     error,
529
362
     LIBCERROR_ERROR_DOMAIN_IO,
530
362
     LIBCERROR_IO_ERROR_READ_FAILED,
531
362
     "%s: unable to read index root node.",
532
362
     function );
533
534
362
    goto on_error;
535
362
  }
536
  /* The index does not necessarily have an $INDEX_ALLOCATION attribute
537
   */
538
899
  if( index_allocation_attribute != NULL )
539
545
  {
540
545
    if( libfsntfs_index_root_header_get_index_entry_size(
541
545
         index->root_header,
542
545
         &index_entry_size,
543
545
         error ) != 1 )
544
1
    {
545
1
      libcerror_error_set(
546
1
       error,
547
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
548
1
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
549
1
       "%s: unable to retrieve index entry size.",
550
1
       function );
551
552
1
      goto on_error;
553
1
    }
554
#if defined( HAVE_DEBUG_OUTPUT )
555
    if( libcnotify_verbose != 0 )
556
    {
557
      if( index_entry_size != index->io_handle->index_entry_size )
558
      {
559
        libcnotify_printf(
560
         "%s: mismatch in index entry size (in index root header: %" PRIu32 ", in volume header: %" PRIu32 ").",
561
         function,
562
         index_entry_size,
563
         index->io_handle->index_entry_size );
564
      }
565
    }
566
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
567
568
544
    if( index_entry_size > index->io_handle->index_entry_size )
569
43
    {
570
43
      libcerror_error_set(
571
43
       error,
572
43
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
573
43
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
574
43
       "%s: invalid index entry size: %" PRIu32 " in index root header value exceeds value in volume header: %" PRIu32 ".",
575
43
       function,
576
43
       index_entry_size,
577
43
       index->io_handle->index_entry_size );
578
579
43
      goto on_error;
580
43
    }
581
501
    if( libfsntfs_index_entry_vector_initialize(
582
501
         &( index->index_entry_vector ),
583
501
         index->io_handle,
584
501
         index_allocation_attribute,
585
501
         index_entry_size,
586
501
         error ) != 1 )
587
343
    {
588
343
      libcerror_error_set(
589
343
       error,
590
343
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
591
343
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
592
343
       "%s: unable to create index entry vector.",
593
343
       function );
594
595
343
      goto on_error;
596
343
    }
597
158
    if( libfcache_cache_initialize(
598
158
         &( index->index_node_cache ),
599
158
         LIBFSNTFS_MAXIMUM_CACHE_ENTRIES_INDEX_NODES,
600
158
         error ) != 1 )
601
0
    {
602
0
      libcerror_error_set(
603
0
       error,
604
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
605
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
606
0
       "%s: unable to create index node cache.",
607
0
       function );
608
609
0
      goto on_error;
610
0
    }
611
158
  }
612
512
  return( 1 );
613
614
1.36k
on_error:
615
1.36k
  if( index->index_node_cache != NULL )
616
0
  {
617
0
    libfcache_cache_free(
618
0
     &( index->index_node_cache ),
619
0
     NULL );
620
0
  }
621
1.36k
  if( index->index_entry_vector != NULL )
622
0
  {
623
0
    libfdata_vector_free(
624
0
     &( index->index_entry_vector ),
625
0
     NULL );
626
0
  }
627
1.36k
  return( -1 );
628
899
}
629
630
/* Reads the index root header
631
 * Returns 1 if successful or -1 on error
632
 */
633
int libfsntfs_index_read_root_header(
634
     libfsntfs_index_t *index,
635
     libfsntfs_mft_attribute_t *index_root_attribute,
636
     libcerror_error_t **error )
637
1.87k
{
638
1.87k
  uint8_t *data         = NULL;
639
1.87k
  static char *function = "libfsntfs_index_read_root_header";
640
1.87k
  size_t data_size      = 0;
641
1.87k
  int result            = 0;
642
643
1.87k
  if( index == NULL )
644
0
  {
645
0
    libcerror_error_set(
646
0
     error,
647
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
648
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
649
0
     "%s: invalid index.",
650
0
     function );
651
652
0
    return( -1 );
653
0
  }
654
1.87k
  if( index->root_header != NULL )
655
0
  {
656
0
    libcerror_error_set(
657
0
     error,
658
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
659
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
660
0
     "%s: invalid index - root header value already set.",
661
0
     function );
662
663
0
    return( -1 );
664
0
  }
665
1.87k
  result = libfsntfs_mft_attribute_data_is_resident(
666
1.87k
            index_root_attribute,
667
1.87k
            error );
668
669
1.87k
  if( result == -1 )
670
0
  {
671
0
    libcerror_error_set(
672
0
     error,
673
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
674
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
675
0
     "%s: unable to determine if index root attribute data is resident.",
676
0
     function );
677
678
0
    return( -1 );
679
0
  }
680
1.87k
  else if( result == 0 )
681
4
  {
682
4
    libcerror_error_set(
683
4
     error,
684
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
685
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
686
4
     "%s: unsupported non-resident index root attribute.",
687
4
     function );
688
689
4
    return( 1 );
690
4
  }
691
1.86k
  if( libfsntfs_mft_attribute_get_resident_data(
692
1.86k
       index_root_attribute,
693
1.86k
       &data,
694
1.86k
       &data_size,
695
1.86k
       error ) != 1 )
696
0
  {
697
0
    libcerror_error_set(
698
0
     error,
699
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
700
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
701
0
     "%s: unable to retrieve index root attribute data.",
702
0
     function );
703
704
0
    goto on_error;
705
0
  }
706
1.86k
  if( libfsntfs_index_root_header_initialize(
707
1.86k
       &( index->root_header ),
708
1.86k
       error ) != 1 )
709
0
  {
710
0
    libcerror_error_set(
711
0
     error,
712
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
713
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
714
0
     "%s: unable to create root header.",
715
0
     function );
716
717
0
    goto on_error;
718
0
  }
719
1.86k
  if( libfsntfs_index_root_header_read_data(
720
1.86k
       index->root_header,
721
1.86k
       data,
722
1.86k
       data_size,
723
1.86k
       error ) != 1 )
724
9
  {
725
9
    libcerror_error_set(
726
9
     error,
727
9
     LIBCERROR_ERROR_DOMAIN_IO,
728
9
     LIBCERROR_IO_ERROR_READ_FAILED,
729
9
     "%s: unable to read root header.",
730
9
     function );
731
732
9
    goto on_error;
733
9
  }
734
1.86k
  return( 1 );
735
736
9
on_error:
737
9
  if( index->root_header != NULL )
738
9
  {
739
9
    libfsntfs_index_root_header_free(
740
9
     &( index->root_header ),
741
9
     NULL );
742
9
  }
743
9
  return( -1 );
744
1.86k
}
745
746
/* Reads the index root node
747
 * Returns 1 if successful or -1 on error
748
 */
749
int libfsntfs_index_read_root_node(
750
     libfsntfs_index_t *index,
751
     libfsntfs_mft_attribute_t *index_root_attribute,
752
     libcerror_error_t **error )
753
1.26k
{
754
1.26k
  uint8_t *data         = NULL;
755
1.26k
  static char *function = "libfsntfs_index_read_root_node";
756
1.26k
  size_t data_offset    = 0;
757
1.26k
  size_t data_size      = 0;
758
1.26k
  int result            = 0;
759
760
1.26k
  if( index == NULL )
761
0
  {
762
0
    libcerror_error_set(
763
0
     error,
764
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
765
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
766
0
     "%s: invalid index.",
767
0
     function );
768
769
0
    return( -1 );
770
0
  }
771
1.26k
  if( index->root_node != NULL )
772
0
  {
773
0
    libcerror_error_set(
774
0
     error,
775
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
776
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
777
0
     "%s: invalid index - root node value already set.",
778
0
     function );
779
780
0
    return( -1 );
781
0
  }
782
1.26k
  result = libfsntfs_mft_attribute_data_is_resident(
783
1.26k
            index_root_attribute,
784
1.26k
            error );
785
786
1.26k
  if( result == -1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
792
0
     "%s: unable to determine if index root attribute data is resident.",
793
0
     function );
794
795
0
    return( -1 );
796
0
  }
797
1.26k
  else if( result == 0 )
798
3
  {
799
3
    libcerror_error_set(
800
3
     error,
801
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
802
3
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
803
3
     "%s: unsupported non-resident index root attribute.",
804
3
     function );
805
806
3
    return( 1 );
807
3
  }
808
1.25k
  if( libfsntfs_mft_attribute_get_resident_data(
809
1.25k
       index_root_attribute,
810
1.25k
       &data,
811
1.25k
       &data_size,
812
1.25k
       error ) != 1 )
813
0
  {
814
0
    libcerror_error_set(
815
0
     error,
816
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
817
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
818
0
     "%s: unable to retrieve index root attribute data.",
819
0
     function );
820
821
0
    goto on_error;
822
0
  }
823
1.25k
  if( libfsntfs_index_node_initialize(
824
1.25k
       &( index->root_node ),
825
1.25k
       error ) != 1 )
826
0
  {
827
0
    libcerror_error_set(
828
0
     error,
829
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
830
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
831
0
     "%s: unable to create index node.",
832
0
     function );
833
834
0
    goto on_error;
835
0
  }
836
1.25k
  data_offset = sizeof( fsntfs_index_root_header_t );
837
838
1.25k
  if( libfsntfs_index_node_read_header(
839
1.25k
       index->root_node,
840
1.25k
       data,
841
1.25k
       data_size,
842
1.25k
       data_offset,
843
1.25k
       error ) != 1 )
844
79
  {
845
79
    libcerror_error_set(
846
79
     error,
847
79
     LIBCERROR_ERROR_DOMAIN_IO,
848
79
     LIBCERROR_IO_ERROR_READ_FAILED,
849
79
     "%s: unable to read index node header.",
850
79
     function );
851
852
79
    goto on_error;
853
79
  }
854
1.17k
  data_offset += sizeof( fsntfs_index_node_header_t );
855
856
1.17k
  index->flags = index->root_node->header->flags;
857
858
1.17k
  if( libfsntfs_index_node_read_values(
859
1.17k
       index->root_node,
860
1.17k
       0,
861
1.17k
       data,
862
1.17k
       data_size,
863
1.17k
       data_offset,
864
1.17k
       error ) != 1 )
865
283
  {
866
283
    libcerror_error_set(
867
283
     error,
868
283
     LIBCERROR_ERROR_DOMAIN_IO,
869
283
     LIBCERROR_IO_ERROR_READ_FAILED,
870
283
     "%s: unable to read index node values.",
871
283
     function );
872
873
283
    goto on_error;
874
283
  }
875
896
  data_offset += index->root_node->header->size;
876
877
#if defined( HAVE_DEBUG_OUTPUT )
878
  if( libcnotify_verbose != 0 )
879
  {
880
    if( data_offset < data_size )
881
    {
882
      libcnotify_printf(
883
       "%s: trailing data:\n",
884
       function );
885
      libcnotify_print_data(
886
       &( data[ data_offset ] ),
887
       data_size - data_offset,
888
       0 );
889
    }
890
  }
891
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
892
893
896
  return( 1 );
894
895
362
on_error:
896
362
  if( index->root_node != NULL )
897
362
  {
898
362
    libfsntfs_index_node_free(
899
362
     &( index->root_node ),
900
362
     NULL );
901
362
  }
902
362
  return( -1 );
903
1.17k
}
904
905
/* Reads the index bitmap
906
 * Returns 1 if successful or -1 on error
907
 */
908
int libfsntfs_index_read_bitmap(
909
     libfsntfs_index_t *index,
910
     libbfio_handle_t *file_io_handle,
911
     libfsntfs_mft_attribute_t *bitmap_attribute,
912
     uint8_t flags,
913
     libcerror_error_t **error )
914
994
{
915
994
  static char *function     = "libfsntfs_index_read_bitmap";
916
994
  uint32_t index_entry_size = 0;
917
918
994
  if( index == NULL )
919
0
  {
920
0
    libcerror_error_set(
921
0
     error,
922
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
923
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
924
0
     "%s: invalid index.",
925
0
     function );
926
927
0
    return( -1 );
928
0
  }
929
994
  if( index->bitmap_values != NULL )
930
0
  {
931
0
    libcerror_error_set(
932
0
     error,
933
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
934
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
935
0
     "%s: invalid index - bitmap values already set.",
936
0
     function );
937
938
0
    return( -1 );
939
0
  }
940
994
  if( libfsntfs_index_root_header_get_index_entry_size(
941
994
       index->root_header,
942
994
       &index_entry_size,
943
994
       error ) != 1 )
944
1
  {
945
1
    libcerror_error_set(
946
1
     error,
947
1
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
948
1
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
949
1
     "%s: unable to retrieve index entry size from root header.",
950
1
     function );
951
952
1
    goto on_error;
953
1
  }
954
993
  if( libfsntfs_bitmap_values_initialize(
955
993
       &( index->bitmap_values ),
956
993
       error ) != 1 )
957
0
  {
958
0
    libcerror_error_set(
959
0
     error,
960
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
961
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
962
0
     "%s: unable to create bitmap values.",
963
0
     function );
964
965
0
    goto on_error;
966
0
  }
967
993
  if( libfsntfs_bitmap_values_read_from_mft_attribute(
968
993
       index->bitmap_values,
969
993
       bitmap_attribute,
970
993
       index->io_handle,
971
993
       file_io_handle,
972
993
       index_entry_size,
973
993
       flags,
974
993
       error ) != 1 )
975
602
  {
976
602
    libcerror_error_set(
977
602
     error,
978
602
     LIBCERROR_ERROR_DOMAIN_IO,
979
602
     LIBCERROR_IO_ERROR_READ_FAILED,
980
602
     "%s: unable to read bitmap values from attribute.",
981
602
     function );
982
983
602
    goto on_error;
984
602
  }
985
391
  return( 1 );
986
987
603
on_error:
988
603
  if( index->bitmap_values != NULL )
989
602
  {
990
602
    libfsntfs_bitmap_values_free(
991
602
     &( index->bitmap_values ),
992
602
     NULL );
993
602
  }
994
603
  return( -1 );
995
993
}
996
997
/* Retrieves the index entry size
998
 * Returns 1 if successful or -1 on error
999
 */
1000
int libfsntfs_index_get_index_entry_size(
1001
     libfsntfs_index_t *index,
1002
     uint32_t *index_entry_size,
1003
     libcerror_error_t **error )
1004
0
{
1005
0
  static char *function = "libfsntfs_index_get_index_entry_size";
1006
1007
0
  if( index == NULL )
1008
0
  {
1009
0
    libcerror_error_set(
1010
0
     error,
1011
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1012
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1013
0
     "%s: invalid index.",
1014
0
     function );
1015
1016
0
    return( -1 );
1017
0
  }
1018
0
  if( libfsntfs_index_root_header_get_index_entry_size(
1019
0
       index->root_header,
1020
0
       index_entry_size,
1021
0
       error ) != 1 )
1022
0
  {
1023
0
    libcerror_error_set(
1024
0
     error,
1025
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1026
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1027
0
     "%s: unable to retrieve index entry size from root header.",
1028
0
     function );
1029
1030
0
    return( -1 );
1031
0
  }
1032
0
  return( 1 );
1033
0
}
1034
1035
/* Retrieves the attribute type
1036
 * Returns 1 if successful or -1 on error
1037
 */
1038
int libfsntfs_index_get_attribute_type(
1039
     libfsntfs_index_t *index,
1040
     uint32_t *attribute_type,
1041
     libcerror_error_t **error )
1042
512
{
1043
512
  static char *function = "libfsntfs_index_get_attribute_type";
1044
1045
512
  if( index == NULL )
1046
0
  {
1047
0
    libcerror_error_set(
1048
0
     error,
1049
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1050
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1051
0
     "%s: invalid index.",
1052
0
     function );
1053
1054
0
    return( -1 );
1055
0
  }
1056
512
  if( libfsntfs_index_root_header_get_attribute_type(
1057
512
       index->root_header,
1058
512
       attribute_type,
1059
512
       error ) != 1 )
1060
2
  {
1061
2
    libcerror_error_set(
1062
2
     error,
1063
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1064
2
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1065
2
     "%s: unable to retrieve attribute type from root header.",
1066
2
     function );
1067
1068
2
    return( -1 );
1069
2
  }
1070
510
  return( 1 );
1071
512
}
1072
1073
/* Retrieves the collation type
1074
 * Returns 1 if successful or -1 on error
1075
 */
1076
int libfsntfs_index_get_collation_type(
1077
     libfsntfs_index_t *index,
1078
     uint32_t *collation_type,
1079
     libcerror_error_t **error )
1080
425
{
1081
425
  static char *function = "libfsntfs_index_get_collation_type";
1082
1083
425
  if( index == NULL )
1084
0
  {
1085
0
    libcerror_error_set(
1086
0
     error,
1087
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1088
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1089
0
     "%s: invalid index.",
1090
0
     function );
1091
1092
0
    return( -1 );
1093
0
  }
1094
425
  if( libfsntfs_index_root_header_get_collation_type(
1095
425
       index->root_header,
1096
425
       collation_type,
1097
425
       error ) != 1 )
1098
0
  {
1099
0
    libcerror_error_set(
1100
0
     error,
1101
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1102
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1103
0
     "%s: unable to retrieve collation type from root header.",
1104
0
     function );
1105
1106
0
    return( -1 );
1107
0
  }
1108
425
  return( 1 );
1109
425
}
1110
1111
/* Determines if a sub node is allocated
1112
 * Returns 1 if allocated, 0 if not or -1 on error
1113
 */
1114
int libfsntfs_index_sub_node_is_allocated(
1115
     libfsntfs_index_t *index,
1116
     int sub_node_vcn,
1117
     libcerror_error_t **error )
1118
869
{
1119
869
  static char *function       = "libfsntfs_index_sub_node_is_allocated";
1120
869
  off64_t sub_node_vcn_offset = 0;
1121
869
  int result                  = 0;
1122
1123
869
  if( index == NULL )
1124
0
  {
1125
0
    libcerror_error_set(
1126
0
     error,
1127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1128
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1129
0
     "%s: invalid index.",
1130
0
     function );
1131
1132
0
    return( -1 );
1133
0
  }
1134
869
  if( index->bitmap_values == NULL )
1135
14
  {
1136
14
    libcerror_error_set(
1137
14
     error,
1138
14
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1139
14
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1140
14
     "%s: invalid index - missing bitmap values.",
1141
14
     function );
1142
1143
14
    return( -1 );
1144
14
  }
1145
855
  if( index->io_handle == NULL )
1146
0
  {
1147
0
    libcerror_error_set(
1148
0
     error,
1149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1151
0
     "%s: invalid index - missing IO handle.",
1152
0
     function );
1153
1154
0
    return( -1 );
1155
0
  }
1156
855
  sub_node_vcn_offset = (off64_t) sub_node_vcn * index->io_handle->cluster_block_size;
1157
1158
855
  result = libcdata_range_list_range_is_present(
1159
855
            index->bitmap_values->allocated_block_list,
1160
855
            sub_node_vcn_offset,
1161
855
            index->io_handle->cluster_block_size,
1162
855
            error );
1163
1164
855
  if( result == -1 )
1165
0
  {
1166
0
    libcerror_error_set(
1167
0
     error,
1168
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1169
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1170
0
     "%s: unable to determine if range of sub node with VCN: %d is allocated.",
1171
0
     function,
1172
0
     sub_node_vcn );
1173
1174
0
    return( -1 );
1175
0
  }
1176
855
  return( result );
1177
855
}
1178
1179
/* Retrieves a sub index node
1180
 * Returns 1 if successful or -1 on error
1181
 */
1182
int libfsntfs_index_get_sub_node(
1183
     libfsntfs_index_t *index,
1184
     libbfio_handle_t *file_io_handle,
1185
     libfcache_cache_t *index_node_cache,
1186
     off64_t index_entry_offset,
1187
     int sub_node_vcn,
1188
     libfsntfs_index_node_t **index_node,
1189
     libcerror_error_t **error )
1190
722
{
1191
722
  static char *function            = "libfsntfs_index_get_sub_node";
1192
722
  off64_t element_data_offset      = 0;
1193
1194
#if defined( HAVE_PROFILER )
1195
  int64_t profiler_start_timestamp = 0;
1196
  uint32_t index_entry_size        = 0;
1197
#endif
1198
1199
722
  if( index == NULL )
1200
0
  {
1201
0
    libcerror_error_set(
1202
0
     error,
1203
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1204
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1205
0
     "%s: invalid index.",
1206
0
     function );
1207
1208
0
    return( -1 );
1209
0
  }
1210
722
  if( index->io_handle == NULL )
1211
0
  {
1212
0
    libcerror_error_set(
1213
0
     error,
1214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1216
0
     "%s: invalid index - missing IO handle.",
1217
0
     function );
1218
1219
0
    return( -1 );
1220
0
  }
1221
#if defined( HAVE_PROFILER )
1222
  if( index->io_handle->profiler != NULL )
1223
  {
1224
    if( libfsntfs_index_root_header_get_index_entry_size(
1225
         index->root_header,
1226
         &index_entry_size,
1227
         error ) != 1 )
1228
    {
1229
      libcerror_error_set(
1230
       error,
1231
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1232
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1233
       "%s: unable to retrieve index entry size.",
1234
       function );
1235
1236
      return( -1 );
1237
    }
1238
    if( libfsntfs_profiler_start_timing(
1239
         index->io_handle->profiler,
1240
         &profiler_start_timestamp,
1241
         error ) != 1 )
1242
    {
1243
      libcerror_error_set(
1244
       error,
1245
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1246
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1247
       "%s: unable to start timing.",
1248
       function );
1249
1250
      return( -1 );
1251
    }
1252
  }
1253
#endif /* defined( HAVE_PROFILER ) */
1254
1255
722
  if( libfdata_vector_get_element_value_at_offset(
1256
722
       index->index_entry_vector,
1257
722
       (intptr_t *) file_io_handle,
1258
722
       (libfdata_cache_t *) index_node_cache,
1259
722
       index_entry_offset,
1260
722
       &element_data_offset,
1261
722
       (intptr_t **) index_node,
1262
722
       0,
1263
722
       error ) != 1 )
1264
77
  {
1265
77
    libcerror_error_set(
1266
77
     error,
1267
77
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1268
77
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1269
77
     "%s: unable to retrieve index node from index entry with VCN: %d at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1270
77
     function,
1271
77
     sub_node_vcn,
1272
77
     index_entry_offset,
1273
77
     index_entry_offset );
1274
1275
77
    return( -1 );
1276
77
  }
1277
#if defined( HAVE_PROFILER )
1278
  if( index->io_handle->profiler != NULL )
1279
  {
1280
    if( libfsntfs_profiler_stop_timing(
1281
         index->io_handle->profiler,
1282
         profiler_start_timestamp,
1283
         function,
1284
         index_entry_offset,
1285
         index_entry_size,
1286
         error ) != 1 )
1287
    {
1288
      libcerror_error_set(
1289
       error,
1290
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1291
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1292
       "%s: unable to stop timing.",
1293
       function );
1294
1295
      return( -1 );
1296
    }
1297
  }
1298
#endif /* defined( HAVE_PROFILER ) */
1299
1300
645
  return( 1 );
1301
722
}
1302