Coverage Report

Created: 2025-03-17 07:10

/src/libfsntfs/libfsntfs/libfsntfs_volume_header.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The NTFS volume header 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_io_handle.h"
28
#include "libfsntfs_libbfio.h"
29
#include "libfsntfs_libcerror.h"
30
#include "libfsntfs_libcnotify.h"
31
#include "libfsntfs_volume_header.h"
32
33
#include "fsntfs_index.h"
34
#include "fsntfs_mft_entry.h"
35
#include "fsntfs_volume_header.h"
36
37
/* Creates a volume header
38
 * Make sure the value volume_header is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsntfs_volume_header_initialize(
42
     libfsntfs_volume_header_t **volume_header,
43
     libcerror_error_t **error )
44
9.33k
{
45
9.33k
  static char *function = "libfsntfs_volume_header_initialize";
46
47
9.33k
  if( volume_header == NULL )
48
0
  {
49
0
    libcerror_error_set(
50
0
     error,
51
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
52
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
53
0
     "%s: invalid volume header.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
9.33k
  if( *volume_header != NULL )
59
0
  {
60
0
    libcerror_error_set(
61
0
     error,
62
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
63
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
64
0
     "%s: invalid volume header value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
9.33k
  *volume_header = memory_allocate_structure(
70
9.33k
                    libfsntfs_volume_header_t );
71
72
9.33k
  if( *volume_header == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
77
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
78
0
     "%s: unable to create volume header.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
9.33k
  if( memory_set(
84
9.33k
       *volume_header,
85
9.33k
       0,
86
9.33k
       sizeof( libfsntfs_volume_header_t ) ) == NULL )
87
0
  {
88
0
    libcerror_error_set(
89
0
     error,
90
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
91
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
92
0
     "%s: unable to clear volume header.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
9.33k
  return( 1 );
98
99
0
on_error:
100
0
  if( *volume_header != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *volume_header );
104
105
0
    *volume_header = NULL;
106
0
  }
107
0
  return( -1 );
108
9.33k
}
109
110
/* Frees a volume header
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libfsntfs_volume_header_free(
114
     libfsntfs_volume_header_t **volume_header,
115
     libcerror_error_t **error )
116
9.33k
{
117
9.33k
  static char *function = "libfsntfs_volume_header_free";
118
119
9.33k
  if( volume_header == NULL )
120
0
  {
121
0
    libcerror_error_set(
122
0
     error,
123
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
124
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
125
0
     "%s: invalid volume header.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
9.33k
  if( *volume_header != NULL )
131
9.33k
  {
132
9.33k
    memory_free(
133
9.33k
     *volume_header );
134
135
9.33k
    *volume_header = NULL;
136
9.33k
  }
137
9.33k
  return( 1 );
138
9.33k
}
139
140
/* Reads the volume header
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfsntfs_volume_header_read_data(
144
     libfsntfs_volume_header_t *volume_header,
145
     const uint8_t *data,
146
     size_t data_size,
147
     libcerror_error_t **error )
148
9.30k
{
149
9.30k
  static char *function                    = "libfsntfs_volume_header_read_data";
150
9.30k
  uint64_t mft_cluster_block_number        = 0;
151
9.30k
  uint64_t mirror_mft_cluster_block_number = 0;
152
153
#if defined( HAVE_DEBUG_OUTPUT )
154
  uint32_t value_32bit                     = 0;
155
  uint16_t value_16bit                     = 0;
156
#endif
157
158
9.30k
  if( volume_header == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid volume header.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
9.30k
  if( data == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
174
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
175
0
     "%s: invalid data.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
9.30k
  if( ( data_size < sizeof( fsntfs_volume_header_t ) )
181
9.30k
   || ( data_size > (size_t) SSIZE_MAX ) )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
187
0
     "%s: invalid data size value out of bounds.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
#if defined( HAVE_DEBUG_OUTPUT )
193
  if( libcnotify_verbose != 0 )
194
  {
195
    libcnotify_printf(
196
     "%s: volume header data:\n",
197
     function );
198
    libcnotify_print_data(
199
     data,
200
     sizeof( fsntfs_volume_header_t ),
201
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
202
  }
203
#endif
204
9.30k
  if( memory_compare(
205
9.30k
       ( (fsntfs_volume_header_t *) data )->file_system_signature,
206
9.30k
       fsntfs_volume_file_system_signature,
207
9.30k
       8 ) != 0 )
208
92
  {
209
92
    libcerror_error_set(
210
92
     error,
211
92
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
212
92
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
213
92
     "%s: invalid volume system signature.",
214
92
     function );
215
216
92
    return( -1 );
217
92
  }
218
9.21k
  byte_stream_copy_to_uint16_little_endian(
219
9.21k
   ( (fsntfs_volume_header_t *) data )->bytes_per_sector,
220
9.21k
   volume_header->bytes_per_sector );
221
222
9.21k
  byte_stream_copy_to_uint64_little_endian(
223
9.21k
   ( (fsntfs_volume_header_t *) data )->total_number_of_sectors,
224
9.21k
   volume_header->volume_size );
225
226
9.21k
  byte_stream_copy_to_uint64_little_endian(
227
9.21k
   ( (fsntfs_volume_header_t *) data )->mft_cluster_block_number,
228
9.21k
   mft_cluster_block_number );
229
230
9.21k
  byte_stream_copy_to_uint64_little_endian(
231
9.21k
   ( (fsntfs_volume_header_t *) data )->mirror_mft_cluster_block_number,
232
9.21k
   mirror_mft_cluster_block_number );
233
234
9.21k
  byte_stream_copy_to_uint32_little_endian(
235
9.21k
   ( (fsntfs_volume_header_t *) data )->mft_entry_size,
236
9.21k
   volume_header->mft_entry_size );
237
238
9.21k
  byte_stream_copy_to_uint32_little_endian(
239
9.21k
   ( (fsntfs_volume_header_t *) data )->index_entry_size,
240
9.21k
   volume_header->index_entry_size );
241
242
9.21k
  byte_stream_copy_to_uint64_little_endian(
243
9.21k
   ( (fsntfs_volume_header_t *) data )->volume_serial_number,
244
9.21k
   volume_header->volume_serial_number );
245
246
#if defined( HAVE_DEBUG_OUTPUT )
247
  if( libcnotify_verbose != 0 )
248
  {
249
    libcnotify_printf(
250
     "%s: boot entry point\t\t\t: 0x%02x 0x%02x 0x%02x\n",
251
     function,
252
     ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 0 ],
253
     ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 1 ],
254
     ( (fsntfs_volume_header_t *) data )->boot_entry_point[ 2 ] );
255
256
    libcnotify_printf(
257
     "%s: file system signature\t\t: %c%c%c%c%c%c%c%c\n",
258
     function,
259
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 0 ],
260
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 1 ],
261
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 2 ],
262
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 3 ],
263
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 4 ],
264
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 5 ],
265
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 6 ],
266
     ( (fsntfs_volume_header_t *) data )->file_system_signature[ 7 ] );
267
268
    libcnotify_printf(
269
     "%s: bytes per sector\t\t\t: %" PRIu16 "\n",
270
     function,
271
     volume_header->bytes_per_sector );
272
273
    libcnotify_printf(
274
     "%s: sectors per cluster block\t\t: %" PRIu8 "\n",
275
     function,
276
     ( (fsntfs_volume_header_t *) data )->sectors_per_cluster_block );
277
278
    libcnotify_printf(
279
     "%s: unknown1\n",
280
     function );
281
    libcnotify_print_data(
282
     ( (fsntfs_volume_header_t *) data )->unknown1,
283
     7,
284
     0 );
285
286
    libcnotify_printf(
287
     "%s: media descriptor\t\t\t: 0x%02" PRIx8 "\n",
288
     function,
289
     ( (fsntfs_volume_header_t *) data )->media_descriptor );
290
291
    byte_stream_copy_to_uint16_little_endian(
292
     ( (fsntfs_volume_header_t *) data )->unknown2,
293
     value_16bit );
294
    libcnotify_printf(
295
     "%s: unknown2\t\t\t\t: %" PRIu16 "\n",
296
     function,
297
     value_16bit );
298
299
    byte_stream_copy_to_uint16_little_endian(
300
     ( (fsntfs_volume_header_t *) data )->sectors_per_track,
301
     value_16bit );
302
    libcnotify_printf(
303
     "%s: sectors per track\t\t\t: %" PRIu16 "\n",
304
     function,
305
     value_16bit );
306
307
    byte_stream_copy_to_uint16_little_endian(
308
     ( (fsntfs_volume_header_t *) data )->number_of_heads,
309
     value_16bit );
310
    libcnotify_printf(
311
     "%s: number of heads\t\t\t: %" PRIu16 "\n",
312
     function,
313
     value_16bit );
314
315
    byte_stream_copy_to_uint32_little_endian(
316
     ( (fsntfs_volume_header_t *) data )->number_of_hidden_sectors,
317
     value_32bit );
318
    libcnotify_printf(
319
     "%s: number of hidden sectors\t\t: %" PRIu32 "\n",
320
     function,
321
     value_32bit );
322
323
    byte_stream_copy_to_uint32_little_endian(
324
     ( (fsntfs_volume_header_t *) data )->unknown3,
325
     value_32bit );
326
    libcnotify_printf(
327
     "%s: unknown3\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
328
     function,
329
     value_32bit,
330
     value_32bit );
331
332
    byte_stream_copy_to_uint32_little_endian(
333
     ( (fsntfs_volume_header_t *) data )->unknown4,
334
     value_32bit );
335
    libcnotify_printf(
336
     "%s: unknown4\t\t\t\t: 0x%08" PRIx32 " (%" PRIu32 ")\n",
337
     function,
338
     value_32bit,
339
     value_32bit );
340
341
    libcnotify_printf(
342
     "%s: total number of sectors\t\t: %" PRIu64 "\n",
343
     function,
344
     volume_header->volume_size );
345
346
    libcnotify_printf(
347
     "%s: MFT cluster block number\t\t: %" PRIu64 "\n",
348
     function,
349
     mft_cluster_block_number );
350
351
    libcnotify_printf(
352
     "%s: mirror MFT cluster block number\t: %" PRIu64 "\n",
353
     function,
354
     mirror_mft_cluster_block_number );
355
356
    libcnotify_printf(
357
     "%s: MFT entry size\t\t\t: %" PRIu32 "\n",
358
     function,
359
     volume_header->mft_entry_size );
360
361
    libcnotify_printf(
362
     "%s: index entry size\t\t\t: %" PRIu32 "\n",
363
     function,
364
     volume_header->index_entry_size );
365
366
    libcnotify_printf(
367
     "%s: volume serial number\t\t\t: 0x%08" PRIx64 "\n",
368
     function,
369
     volume_header->volume_serial_number );
370
371
    byte_stream_copy_to_uint32_little_endian(
372
     ( (fsntfs_volume_header_t *) data )->checksum,
373
     value_32bit );
374
    libcnotify_printf(
375
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
376
     function,
377
     value_32bit );
378
379
    libcnotify_printf(
380
     "%s: bootcode\n",
381
     function );
382
    libcnotify_print_data(
383
     ( (fsntfs_volume_header_t *) data )->bootcode,
384
     426,
385
     0 );
386
387
    byte_stream_copy_to_uint16_little_endian(
388
     ( (fsntfs_volume_header_t *) data )->sector_signature,
389
     value_16bit );
390
    libcnotify_printf(
391
     "%s: sector signature\t\t\t: 0x%04" PRIx16 "\n",
392
     function,
393
     value_16bit );
394
395
    libcnotify_printf(
396
     "\n" );
397
  }
398
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
399
400
9.21k
  if( ( volume_header->bytes_per_sector != 256 )
401
9.21k
   && ( volume_header->bytes_per_sector != 512 )
402
9.21k
   && ( volume_header->bytes_per_sector != 1024 )
403
9.21k
   && ( volume_header->bytes_per_sector != 2048 )
404
9.21k
   && ( volume_header->bytes_per_sector != 4096 ) )
405
83
  {
406
83
    libcerror_error_set(
407
83
     error,
408
83
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
409
83
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
410
83
     "%s: unsupported bytes per sector: %" PRIu16 ".",
411
83
     function,
412
83
     volume_header->bytes_per_sector );
413
414
83
    return( -1 );
415
83
  }
416
9.12k
  volume_header->cluster_block_size = ( (fsntfs_volume_header_t *) data )->sectors_per_cluster_block;
417
418
9.12k
  if( volume_header->cluster_block_size > 128 )
419
94
  {
420
    /* The size is calculated as: 2 ^ ( 256 - value )
421
     */
422
94
    volume_header->cluster_block_size = 256 - volume_header->cluster_block_size;
423
424
94
    if( volume_header->cluster_block_size > 12 )
425
7
    {
426
7
      libcerror_error_set(
427
7
       error,
428
7
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
429
7
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
430
7
       "%s: invalid cluster block size value out of bounds.",
431
7
       function );
432
433
7
      return( -1 );
434
7
    }
435
87
    volume_header->cluster_block_size = 1 << volume_header->cluster_block_size;
436
87
  }
437
9.12k
  volume_header->cluster_block_size *= volume_header->bytes_per_sector;
438
439
9.12k
  if( ( volume_header->cluster_block_size != 256 )
440
9.12k
   && ( volume_header->cluster_block_size != 512 )
441
9.12k
   && ( volume_header->cluster_block_size != 1024 )
442
9.12k
   && ( volume_header->cluster_block_size != 2048 )
443
9.12k
   && ( volume_header->cluster_block_size != 4096 )
444
9.12k
   && ( volume_header->cluster_block_size != 8192 )
445
9.12k
   && ( volume_header->cluster_block_size != 16384 )
446
9.12k
   && ( volume_header->cluster_block_size != 32768 )
447
9.12k
   && ( volume_header->cluster_block_size != 65536 )
448
9.12k
   && ( volume_header->cluster_block_size != 131072 )
449
9.12k
   && ( volume_header->cluster_block_size != 262144 )
450
9.12k
   && ( volume_header->cluster_block_size != 524288 )
451
9.12k
   && ( volume_header->cluster_block_size != 1048576 )
452
9.12k
   && ( volume_header->cluster_block_size != 2097152 ) )
453
79
  {
454
79
    libcerror_error_set(
455
79
     error,
456
79
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
457
79
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
458
79
     "%s: unsupported cluster block size: %" PRIu32 ".",
459
79
     function,
460
79
     volume_header->cluster_block_size );
461
462
79
    return( -1 );
463
79
  }
464
9.04k
  if( ( volume_header->mft_entry_size == 0 )
465
9.04k
   || ( volume_header->mft_entry_size > 255 ) )
466
84
  {
467
84
    libcerror_error_set(
468
84
     error,
469
84
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
470
84
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
471
84
     "%s: unsupported MFT entry size: %" PRIu32 ".",
472
84
     function,
473
84
     volume_header->mft_entry_size );
474
475
84
    return( -1 );
476
84
  }
477
8.95k
  if( volume_header->mft_entry_size < 128 )
478
5.63k
  {
479
5.63k
    if( volume_header->mft_entry_size >= (size32_t) ( ( UINT32_MAX / volume_header->cluster_block_size ) + 1 ) )
480
0
    {
481
0
      libcerror_error_set(
482
0
       error,
483
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
484
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
485
0
       "%s: invalid MFT entry size value out of bounds.",
486
0
       function );
487
488
0
      return( -1 );
489
0
    }
490
5.63k
    volume_header->mft_entry_size *= volume_header->cluster_block_size;
491
5.63k
  }
492
3.32k
  else
493
3.32k
  {
494
    /* The size is calculated as: 2 ^ ( 256 - value )
495
     */
496
3.32k
    volume_header->mft_entry_size = 256 - volume_header->mft_entry_size;
497
498
3.32k
    if( volume_header->mft_entry_size >= 32 )
499
13
    {
500
13
      libcerror_error_set(
501
13
       error,
502
13
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
503
13
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
504
13
       "%s: invalid MFT entry size value out of bounds.",
505
13
       function );
506
507
13
      return( -1 );
508
13
    }
509
3.30k
    volume_header->mft_entry_size = (uint32_t) 1UL << volume_header->mft_entry_size;
510
3.30k
  }
511
8.94k
  if( ( (size_t) volume_header->mft_entry_size < sizeof( fsntfs_mft_entry_header_t ) )
512
8.94k
   || ( volume_header->mft_entry_size >= (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
513
10
  {
514
10
    libcerror_error_set(
515
10
     error,
516
10
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
517
10
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
518
10
     "%s: invalid MFT entry size: %" PRIu32 " value out of bounds.",
519
10
     function,
520
10
     volume_header->mft_entry_size );
521
522
10
    return( -1 );
523
10
  }
524
8.93k
  if( ( volume_header->index_entry_size == 0 )
525
8.93k
   || ( volume_header->index_entry_size > 255 ) )
526
77
  {
527
77
    libcerror_error_set(
528
77
     error,
529
77
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
530
77
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
531
77
     "%s: unsupported index entry size: %" PRIu32 ".",
532
77
     function,
533
77
     volume_header->index_entry_size );
534
535
77
    return( -1 );
536
77
  }
537
8.85k
  if( volume_header->index_entry_size < 128 )
538
7.98k
  {
539
7.98k
    if( volume_header->index_entry_size >= (size32_t) ( ( UINT32_MAX / volume_header->cluster_block_size ) + 1 ) )
540
0
    {
541
0
      libcerror_error_set(
542
0
       error,
543
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
544
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
545
0
       "%s: invalid index entry size value out of bounds.",
546
0
       function );
547
548
0
      return( -1 );
549
0
    }
550
7.98k
    volume_header->index_entry_size *= volume_header->cluster_block_size;
551
7.98k
  }
552
873
  else
553
873
  {
554
    /* The size is calculated as: 2 ^ ( 256 - value )
555
     */
556
873
    volume_header->index_entry_size = 256 - volume_header->index_entry_size;
557
558
873
    if( volume_header->index_entry_size >= 32 )
559
14
    {
560
14
      libcerror_error_set(
561
14
       error,
562
14
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
563
14
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
564
14
       "%s: invalid index entry size value out of bounds.",
565
14
       function );
566
567
14
      return( -1 );
568
14
    }
569
859
    volume_header->index_entry_size = (uint32_t) 1UL << volume_header->index_entry_size;
570
859
  }
571
8.84k
  if( (size_t) volume_header->index_entry_size < sizeof( fsntfs_index_entry_header_t ) )
572
3
  {
573
3
    libcerror_error_set(
574
3
     error,
575
3
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
576
3
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
577
3
     "%s: invalid index entry size: %" PRIu32 " value out of bounds.",
578
3
     function,
579
3
     volume_header->index_entry_size );
580
581
3
    return( -1 );
582
3
  }
583
8.84k
  if( volume_header->volume_size > (size64_t) ( ( UINT64_MAX / volume_header->bytes_per_sector ) + 1 ) )
584
117
  {
585
117
    libcerror_error_set(
586
117
     error,
587
117
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
588
117
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
589
117
     "%s: invalid volume size value out of bounds.",
590
117
     function );
591
592
117
    return( -1 );
593
117
  }
594
8.72k
  volume_header->volume_size *= volume_header->bytes_per_sector;
595
8.72k
  volume_header->volume_size += volume_header->bytes_per_sector;
596
597
8.72k
  volume_header->mft_offset = mft_cluster_block_number
598
8.72k
                            * volume_header->cluster_block_size;
599
600
8.72k
  volume_header->mirror_mft_offset = mirror_mft_cluster_block_number
601
8.72k
                                   * volume_header->cluster_block_size;
602
603
#if defined( HAVE_DEBUG_OUTPUT )
604
  if( libcnotify_verbose != 0 )
605
  {
606
    libcnotify_printf(
607
     "%s: calculated cluster block size\t: %" PRIu32 "\n",
608
     function,
609
     volume_header->cluster_block_size );
610
611
    libcnotify_printf(
612
     "%s: calculated MFT entry size\t\t: %" PRIu32 "\n",
613
     function,
614
     volume_header->mft_entry_size );
615
616
    libcnotify_printf(
617
     "%s: calculated index entry size\t\t: %" PRIu32 "\n",
618
     function,
619
     volume_header->index_entry_size );
620
621
    libcnotify_printf(
622
     "%s: calculated volume size\t\t: %" PRIu64 "\n",
623
     function,
624
     volume_header->volume_size );
625
626
    libcnotify_printf(
627
     "%s: calculated MFT offset\t\t: 0x%08" PRIx64 "\n",
628
     function,
629
     volume_header->mft_offset );
630
631
    libcnotify_printf(
632
     "%s: calculated mirror MFT offset\t\t: 0x%08" PRIx64 "\n",
633
     function,
634
     volume_header->mirror_mft_offset );
635
636
    libcnotify_printf(
637
     "\n" );
638
  }
639
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
640
641
8.72k
  return( 1 );
642
8.84k
}
643
644
/* Reads the volume header
645
 * Returns 1 if successful or -1 on error
646
 */
647
int libfsntfs_volume_header_read_file_io_handle(
648
     libfsntfs_volume_header_t *volume_header,
649
     libbfio_handle_t *file_io_handle,
650
     off64_t file_offset,
651
     libcerror_error_t **error )
652
9.33k
{
653
9.33k
  uint8_t volume_header_data[ sizeof( fsntfs_volume_header_t ) ];
654
655
9.33k
  static char *function = "libfsntfs_volume_header_read_file_io_handle";
656
9.33k
  ssize_t read_count    = 0;
657
658
9.33k
  if( volume_header == NULL )
659
0
  {
660
0
    libcerror_error_set(
661
0
     error,
662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
664
0
     "%s: invalid volume header.",
665
0
     function );
666
667
0
    return( -1 );
668
0
  }
669
#if defined( HAVE_DEBUG_OUTPUT )
670
  if( libcnotify_verbose != 0 )
671
  {
672
    libcnotify_printf(
673
     "%s: reading volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
674
     function,
675
     file_offset,
676
     file_offset );
677
  }
678
#endif
679
9.33k
  read_count = libbfio_handle_read_buffer_at_offset(
680
9.33k
                file_io_handle,
681
9.33k
                volume_header_data,
682
9.33k
                sizeof( fsntfs_volume_header_t ),
683
9.33k
                file_offset,
684
9.33k
                error );
685
686
9.33k
  if( read_count != (ssize_t) sizeof( fsntfs_volume_header_t ) )
687
32
  {
688
32
    libcerror_error_set(
689
32
     error,
690
32
     LIBCERROR_ERROR_DOMAIN_IO,
691
32
     LIBCERROR_IO_ERROR_READ_FAILED,
692
32
     "%s: unable to read volume header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
693
32
     function,
694
32
     file_offset,
695
32
     file_offset );
696
697
32
    return( -1 );
698
32
  }
699
9.30k
  if( libfsntfs_volume_header_read_data(
700
9.30k
       volume_header,
701
9.30k
       volume_header_data,
702
9.30k
       sizeof( fsntfs_volume_header_t ),
703
9.30k
       error ) != 1 )
704
579
  {
705
579
    libcerror_error_set(
706
579
     error,
707
579
     LIBCERROR_ERROR_DOMAIN_IO,
708
579
     LIBCERROR_IO_ERROR_READ_FAILED,
709
579
     "%s: unable to read volume header data.",
710
579
     function );
711
712
579
    return( -1 );
713
579
  }
714
8.72k
  return( 1 );
715
9.30k
}
716
717
/* Retrieves the bytes per sector
718
 * Returns 1 if successful or -1 on error
719
 */
720
int libfsntfs_volume_header_get_bytes_per_sector(
721
     libfsntfs_volume_header_t *volume_header,
722
     uint16_t *bytes_per_sector,
723
     libcerror_error_t **error )
724
8.72k
{
725
8.72k
  static char *function = "libfsntfs_volume_header_get_bytes_per_sector";
726
727
8.72k
  if( volume_header == NULL )
728
0
  {
729
0
    libcerror_error_set(
730
0
     error,
731
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
732
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
733
0
     "%s: invalid volume header.",
734
0
     function );
735
736
0
    return( -1 );
737
0
  }
738
8.72k
  if( bytes_per_sector == NULL )
739
0
  {
740
0
    libcerror_error_set(
741
0
     error,
742
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
743
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
744
0
     "%s: invalid bytes per sector.",
745
0
     function );
746
747
0
    return( -1 );
748
0
  }
749
8.72k
  *bytes_per_sector = volume_header->bytes_per_sector;
750
751
8.72k
  return( 1 );
752
8.72k
}
753
754
/* Retrieves the cluster block size
755
 * Returns 1 if successful or -1 on error
756
 */
757
int libfsntfs_volume_header_get_cluster_block_size(
758
     libfsntfs_volume_header_t *volume_header,
759
     size32_t *cluster_block_size,
760
     libcerror_error_t **error )
761
8.72k
{
762
8.72k
  static char *function = "libfsntfs_volume_header_get_cluster_block_size";
763
764
8.72k
  if( volume_header == NULL )
765
0
  {
766
0
    libcerror_error_set(
767
0
     error,
768
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
769
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
770
0
     "%s: invalid volume header.",
771
0
     function );
772
773
0
    return( -1 );
774
0
  }
775
8.72k
  if( cluster_block_size == NULL )
776
0
  {
777
0
    libcerror_error_set(
778
0
     error,
779
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
780
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
781
0
     "%s: invalid cluster block size.",
782
0
     function );
783
784
0
    return( -1 );
785
0
  }
786
8.72k
  *cluster_block_size = volume_header->cluster_block_size;
787
788
8.72k
  return( 1 );
789
8.72k
}
790
791
/* Retrieves the MFT entry size
792
 * Returns 1 if successful or -1 on error
793
 */
794
int libfsntfs_volume_header_get_mft_entry_size(
795
     libfsntfs_volume_header_t *volume_header,
796
     size32_t *mft_entry_size,
797
     libcerror_error_t **error )
798
8.72k
{
799
8.72k
  static char *function = "libfsntfs_volume_header_get_mft_entry_size";
800
801
8.72k
  if( volume_header == NULL )
802
0
  {
803
0
    libcerror_error_set(
804
0
     error,
805
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
806
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
807
0
     "%s: invalid volume header.",
808
0
     function );
809
810
0
    return( -1 );
811
0
  }
812
8.72k
  if( mft_entry_size == NULL )
813
0
  {
814
0
    libcerror_error_set(
815
0
     error,
816
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
817
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
818
0
     "%s: invalid MFT entry size.",
819
0
     function );
820
821
0
    return( -1 );
822
0
  }
823
8.72k
  *mft_entry_size = volume_header->mft_entry_size;
824
825
8.72k
  return( 1 );
826
8.72k
}
827
828
/* Retrieves the index entry size
829
 * Returns 1 if successful or -1 on error
830
 */
831
int libfsntfs_volume_header_get_index_entry_size(
832
     libfsntfs_volume_header_t *volume_header,
833
     size32_t *index_entry_size,
834
     libcerror_error_t **error )
835
8.72k
{
836
8.72k
  static char *function = "libfsntfs_volume_header_get_index_entry_size";
837
838
8.72k
  if( volume_header == NULL )
839
0
  {
840
0
    libcerror_error_set(
841
0
     error,
842
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
843
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
844
0
     "%s: invalid volume header.",
845
0
     function );
846
847
0
    return( -1 );
848
0
  }
849
8.72k
  if( index_entry_size == NULL )
850
0
  {
851
0
    libcerror_error_set(
852
0
     error,
853
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
854
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
855
0
     "%s: invalid index entry size.",
856
0
     function );
857
858
0
    return( -1 );
859
0
  }
860
8.72k
  *index_entry_size = volume_header->index_entry_size;
861
862
8.72k
  return( 1 );
863
8.72k
}
864
865
/* Retrieves the volume size
866
 * Returns 1 if successful or -1 on error
867
 */
868
int libfsntfs_volume_header_get_volume_size(
869
     libfsntfs_volume_header_t *volume_header,
870
     size64_t *volume_size,
871
     libcerror_error_t **error )
872
0
{
873
0
  static char *function = "libfsntfs_volume_header_get_volume_size";
874
875
0
  if( volume_header == NULL )
876
0
  {
877
0
    libcerror_error_set(
878
0
     error,
879
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
880
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
881
0
     "%s: invalid volume header.",
882
0
     function );
883
884
0
    return( -1 );
885
0
  }
886
0
  if( volume_size == NULL )
887
0
  {
888
0
    libcerror_error_set(
889
0
     error,
890
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
891
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
892
0
     "%s: invalid volume size.",
893
0
     function );
894
895
0
    return( -1 );
896
0
  }
897
0
  *volume_size = volume_header->volume_size;
898
899
0
  return( 1 );
900
0
}
901
902
/* Retrieves the volume serial number
903
 * Returns 1 if successful or -1 on error
904
 */
905
int libfsntfs_volume_header_get_volume_serial_number(
906
     libfsntfs_volume_header_t *volume_header,
907
     uint64_t *volume_serial_number,
908
     libcerror_error_t **error )
909
0
{
910
0
  static char *function = "libfsntfs_volume_header_get_volume_serial_number";
911
912
0
  if( volume_header == NULL )
913
0
  {
914
0
    libcerror_error_set(
915
0
     error,
916
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
917
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
918
0
     "%s: invalid volume header.",
919
0
     function );
920
921
0
    return( -1 );
922
0
  }
923
0
  if( volume_serial_number == NULL )
924
0
  {
925
0
    libcerror_error_set(
926
0
     error,
927
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
928
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
929
0
     "%s: invalid volume serial number.",
930
0
     function );
931
932
0
    return( -1 );
933
0
  }
934
0
  *volume_serial_number = volume_header->volume_serial_number;
935
936
0
  return( 1 );
937
0
}
938
939
/* Retrieves the MFT offset
940
 * Returns 1 if successful or -1 on error
941
 */
942
int libfsntfs_volume_header_get_mft_offset(
943
     libfsntfs_volume_header_t *volume_header,
944
     off64_t *mft_offset,
945
     libcerror_error_t **error )
946
8.72k
{
947
8.72k
  static char *function = "libfsntfs_volume_header_get_mft_offset";
948
949
8.72k
  if( volume_header == NULL )
950
0
  {
951
0
    libcerror_error_set(
952
0
     error,
953
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
954
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
955
0
     "%s: invalid volume header.",
956
0
     function );
957
958
0
    return( -1 );
959
0
  }
960
8.72k
  if( mft_offset == NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
965
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
966
0
     "%s: invalid MFT offset.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
8.72k
  *mft_offset = volume_header->mft_offset;
972
973
8.72k
  return( 1 );
974
8.72k
}
975