Coverage Report

Created: 2026-05-30 07:13

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