Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfsext/libfsext/libfsext_superblock.c
Line
Count
Source
1
/*
2
 * Superblock 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 <byte_stream.h>
24
#include <memory.h>
25
#include <narrow_string.h>
26
#include <system_string.h>
27
#include <types.h>
28
#include <wide_string.h>
29
30
#include "libfsext_checksum.h"
31
#include "libfsext_debug.h"
32
#include "libfsext_definitions.h"
33
#include "libfsext_libbfio.h"
34
#include "libfsext_libcerror.h"
35
#include "libfsext_libcnotify.h"
36
#include "libfsext_libfdatetime.h"
37
#include "libfsext_libfguid.h"
38
#include "libfsext_libuna.h"
39
#include "libfsext_superblock.h"
40
41
#include "fsext_superblock.h"
42
43
const char *fsext_superblock_signature = "\x53\xef";
44
45
/* Creates a superblock
46
 * Make sure the value superblock is referencing, is set to NULL
47
 * Returns 1 if successful or -1 on error
48
 */
49
int libfsext_superblock_initialize(
50
     libfsext_superblock_t **superblock,
51
     libcerror_error_t **error )
52
9.62k
{
53
9.62k
  static char *function = "libfsext_superblock_initialize";
54
55
9.62k
  if( superblock == 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 superblock.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
9.62k
  if( *superblock != 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 superblock value already set.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
9.62k
  *superblock = memory_allocate_structure(
78
9.62k
                 libfsext_superblock_t );
79
80
9.62k
  if( *superblock == 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 superblock.",
87
0
     function );
88
89
0
    goto on_error;
90
0
  }
91
9.62k
  if( memory_set(
92
9.62k
       *superblock,
93
9.62k
       0,
94
9.62k
       sizeof( libfsext_superblock_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 superblock.",
101
0
     function );
102
103
0
    goto on_error;
104
0
  }
105
9.62k
  return( 1 );
106
107
0
on_error:
108
0
  if( *superblock != NULL )
109
0
  {
110
0
    memory_free(
111
0
     *superblock );
112
113
0
    *superblock = NULL;
114
0
  }
115
0
  return( -1 );
116
9.62k
}
117
118
/* Frees a superblock
119
 * Returns 1 if successful or -1 on error
120
 */
121
int libfsext_superblock_free(
122
     libfsext_superblock_t **superblock,
123
     libcerror_error_t **error )
124
9.62k
{
125
9.62k
  static char *function = "libfsext_superblock_free";
126
127
9.62k
  if( superblock == NULL )
128
0
  {
129
0
    libcerror_error_set(
130
0
     error,
131
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
132
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
133
0
     "%s: invalid superblock.",
134
0
     function );
135
136
0
    return( -1 );
137
0
  }
138
9.62k
  if( *superblock != NULL )
139
9.62k
  {
140
9.62k
    memory_free(
141
9.62k
     *superblock );
142
143
9.62k
    *superblock = NULL;
144
9.62k
  }
145
9.62k
  return( 1 );
146
9.62k
}
147
148
/* Reads the superblock data
149
 * Returns 1 if successful, 0 if signature does not match or -1 on error
150
 */
151
int libfsext_superblock_read_data(
152
     libfsext_superblock_t *superblock,
153
     const uint8_t *data,
154
     size_t data_size,
155
     libcerror_error_t **error )
156
9.41k
{
157
9.41k
  static char *function                         = "libfsext_superblock_read_data";
158
9.41k
  uint32_t calculated_checksum                  = 0;
159
9.41k
  uint32_t stored_checksum                      = 0;
160
9.41k
  uint32_t supported_feature_flags              = 0;
161
9.41k
  uint8_t checksum_type                         = 0;
162
9.41k
  uint8_t number_of_block_groups_per_flex_group = 0;
163
164
#if defined( HAVE_DEBUG_OUTPUT )
165
  uint64_t value_64bit                          = 0;
166
  uint32_t value_32bit                          = 0;
167
  uint16_t value_16bit                          = 0;
168
#endif
169
170
9.41k
  if( superblock == NULL )
171
0
  {
172
0
    libcerror_error_set(
173
0
     error,
174
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
175
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
176
0
     "%s: invalid superblock.",
177
0
     function );
178
179
0
    return( -1 );
180
0
  }
181
9.41k
  if( data == NULL )
182
0
  {
183
0
    libcerror_error_set(
184
0
     error,
185
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
186
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
187
0
     "%s: invalid data.",
188
0
     function );
189
190
0
    return( -1 );
191
0
  }
192
9.41k
  if( data_size < sizeof( fsext_superblock_ext2_t ) )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
197
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
198
0
     "%s: invalid data size value too small.",
199
0
     function );
200
201
0
    return( -1 );
202
0
  }
203
9.41k
  if( data_size > (size_t) SSIZE_MAX )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
208
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
209
0
     "%s: invalid data size value exceeds maximum.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
#if defined( HAVE_DEBUG_OUTPUT )
215
  if( libcnotify_verbose != 0 )
216
  {
217
    libcnotify_printf(
218
     "%s: superblock data:\n",
219
     function );
220
    libcnotify_print_data(
221
     data,
222
     sizeof( fsext_superblock_ext2_t ),
223
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
224
  }
225
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
226
227
9.41k
  if( memory_compare(
228
9.41k
       ( (fsext_superblock_ext2_t *) data )->signature,
229
9.41k
       fsext_superblock_signature,
230
9.41k
       2 ) != 0 )
231
303
  {
232
303
    return( 0 );
233
303
  }
234
9.11k
  byte_stream_copy_to_uint32_little_endian(
235
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_inodes,
236
9.11k
   superblock->number_of_inodes );
237
238
9.11k
  byte_stream_copy_to_uint32_little_endian(
239
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_blocks,
240
9.11k
   superblock->number_of_blocks );
241
242
9.11k
  byte_stream_copy_to_uint32_little_endian(
243
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_reserved_blocks,
244
9.11k
   superblock->number_of_reserved_blocks );
245
246
9.11k
  byte_stream_copy_to_uint32_little_endian(
247
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_unallocated_blocks,
248
9.11k
   superblock->number_of_unallocated_blocks );
249
250
9.11k
  byte_stream_copy_to_uint32_little_endian(
251
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_unallocated_inodes,
252
9.11k
   superblock->number_of_unallocated_inodes );
253
254
9.11k
  byte_stream_copy_to_uint32_little_endian(
255
9.11k
   ( (fsext_superblock_ext2_t *) data )->block_size,
256
9.11k
   superblock->block_size );
257
258
9.11k
  byte_stream_copy_to_uint32_little_endian(
259
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_blocks_per_block_group,
260
9.11k
   superblock->number_of_blocks_per_block_group );
261
262
9.11k
  byte_stream_copy_to_uint32_little_endian(
263
9.11k
   ( (fsext_superblock_ext2_t *) data )->format_revision,
264
9.11k
   superblock->format_revision );
265
266
9.11k
  byte_stream_copy_to_uint32_little_endian(
267
9.11k
   ( (fsext_superblock_ext2_t *) data )->number_of_inodes_per_block_group,
268
9.11k
   superblock->number_of_inodes_per_block_group );
269
270
9.11k
  byte_stream_copy_to_uint32_little_endian(
271
9.11k
   ( (fsext_superblock_ext2_t *) data )->last_mount_time,
272
9.11k
   superblock->last_mount_time );
273
274
9.11k
  byte_stream_copy_to_uint32_little_endian(
275
9.11k
   ( (fsext_superblock_ext2_t *) data )->last_written_time,
276
9.11k
   superblock->last_written_time );
277
278
#if defined( HAVE_DEBUG_OUTPUT )
279
  if( libcnotify_verbose != 0 )
280
  {
281
    libcnotify_printf(
282
     "%s: number of inodes\t\t\t\t\t: %" PRIu32 "\n",
283
     function,
284
     superblock->number_of_inodes );
285
286
    libcnotify_printf(
287
     "%s: number of blocks\t\t\t\t\t: %" PRIu32 "\n",
288
     function,
289
     superblock->number_of_blocks );
290
291
    libcnotify_printf(
292
     "%s: number of reserved blocks\t\t\t: %" PRIu32 "\n",
293
     function,
294
     superblock->number_of_reserved_blocks );
295
296
    libcnotify_printf(
297
     "%s: number of unallocated blocks\t\t\t: %" PRIu32 "\n",
298
     function,
299
     superblock->number_of_unallocated_blocks );
300
301
    libcnotify_printf(
302
     "%s: number of unallocated inodes\t\t\t: %" PRIu32 "\n",
303
     function,
304
     superblock->number_of_unallocated_inodes );
305
306
    byte_stream_copy_to_uint32_little_endian(
307
     ( (fsext_superblock_ext2_t *) data )->first_data_block_number,
308
     value_32bit );
309
    libcnotify_printf(
310
     "%s: first data block number\t\t\t\t: %" PRIu32 "\n",
311
     function,
312
     value_32bit );
313
314
    libcnotify_printf(
315
     "%s: block size\t\t\t\t\t: %" PRIu64 " (%" PRIu32 ")\n",
316
     function,
317
     (uint64_t) 1024UL << superblock->block_size,
318
     superblock->block_size );
319
320
    byte_stream_copy_to_uint32_little_endian(
321
     ( (fsext_superblock_ext2_t *) data )->fragment_size,
322
     value_32bit );
323
    libcnotify_printf(
324
     "%s: fragment size\t\t\t\t\t: %" PRIu32 " (%" PRIu32 ")\n",
325
     function,
326
     1024 << value_32bit,
327
     value_32bit );
328
329
    libcnotify_printf(
330
     "%s: number of blocks per block group\t\t\t: %" PRIu32 "\n",
331
     function,
332
     superblock->number_of_blocks_per_block_group );
333
334
    byte_stream_copy_to_uint32_little_endian(
335
     ( (fsext_superblock_ext2_t *) data )->number_of_fragments_per_block_group,
336
     value_32bit );
337
    libcnotify_printf(
338
     "%s: number of fragments per block group\t\t: %" PRIu32 "\n",
339
     function,
340
     value_32bit );
341
342
    libcnotify_printf(
343
     "%s: number of inodes per block group\t\t\t: %" PRIu32 "\n",
344
     function,
345
     superblock->number_of_inodes_per_block_group );
346
347
    if( libfsext_debug_print_posix_time_value(
348
         function,
349
         "last mount time\t\t\t\t\t",
350
         ( (fsext_superblock_ext2_t *) data )->last_mount_time,
351
         4,
352
         LIBFDATETIME_ENDIAN_LITTLE,
353
         LIBFDATETIME_POSIX_TIME_VALUE_TYPE_SECONDS_32BIT_SIGNED,
354
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
355
         error ) != 1 )
356
    {
357
      libcerror_error_set(
358
       error,
359
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
361
       "%s: unable to print posix time value.",
362
       function );
363
364
      return( -1 );
365
    }
366
    if( libfsext_debug_print_posix_time_value(
367
         function,
368
         "last written time\t\t\t\t",
369
         ( (fsext_superblock_ext2_t *) data )->last_written_time,
370
         4,
371
         LIBFDATETIME_ENDIAN_LITTLE,
372
         LIBFDATETIME_POSIX_TIME_VALUE_TYPE_SECONDS_32BIT_SIGNED,
373
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
374
         error ) != 1 )
375
    {
376
      libcerror_error_set(
377
       error,
378
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
379
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
380
       "%s: unable to print posix time value.",
381
       function );
382
383
      return( -1 );
384
    }
385
    byte_stream_copy_to_uint16_little_endian(
386
     ( (fsext_superblock_ext2_t *) data )->mount_count,
387
     value_16bit );
388
    libcnotify_printf(
389
     "%s: mount count\t\t\t\t\t: %" PRIu16 "\n",
390
     function,
391
     value_16bit );
392
393
    byte_stream_copy_to_uint16_little_endian(
394
     ( (fsext_superblock_ext2_t *) data )->maximum_mount_count,
395
     value_16bit );
396
    libcnotify_printf(
397
     "%s: maximum mount count\t\t\t\t: %" PRIu16 "\n",
398
     function,
399
     value_16bit );
400
401
    libcnotify_printf(
402
     "%s: signature\t\t\t\t\t: 0x%02" PRIx8 " 0x%02" PRIx8 "\n",
403
     function,
404
     ( (fsext_superblock_ext2_t *) data )->signature[ 0 ],
405
     ( (fsext_superblock_ext2_t *) data )->signature[ 1 ] );
406
407
    byte_stream_copy_to_uint16_little_endian(
408
     ( (fsext_superblock_ext2_t *) data )->file_system_state_flags,
409
     value_16bit );
410
    libcnotify_printf(
411
     "%s: file system state flags\t\t\t\t: 0x%04" PRIx16 "\n",
412
     function,
413
     value_16bit );
414
    libfsext_debug_print_file_system_state_flags(
415
     value_16bit );
416
    libcnotify_printf(
417
     "\n" );
418
419
    byte_stream_copy_to_uint16_little_endian(
420
     ( (fsext_superblock_ext2_t *) data )->error_handling_status,
421
     value_16bit );
422
    libcnotify_printf(
423
     "%s: error handling status\t\t\t\t: %" PRIu16 " (%s)\n",
424
     function,
425
     value_16bit,
426
     libfsext_debug_print_error_handling_status(
427
      value_16bit ) );
428
429
    byte_stream_copy_to_uint16_little_endian(
430
     ( (fsext_superblock_ext2_t *) data )->minor_format_revision,
431
     value_16bit );
432
    libcnotify_printf(
433
     "%s: minor format revision\t\t\t\t: %" PRIu16 "\n",
434
     function,
435
     value_16bit );
436
437
    if( libfsext_debug_print_posix_time_value(
438
         function,
439
         "last consistency check time\t\t\t",
440
         ( (fsext_superblock_ext2_t *) data )->last_consistency_check_time,
441
         4,
442
         LIBFDATETIME_ENDIAN_LITTLE,
443
         LIBFDATETIME_POSIX_TIME_VALUE_TYPE_SECONDS_32BIT_SIGNED,
444
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
445
         error ) != 1 )
446
    {
447
      libcerror_error_set(
448
       error,
449
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
450
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
451
       "%s: unable to print posix time value.",
452
       function );
453
454
      return( -1 );
455
    }
456
457
/* TODO print interval as duration? */
458
    byte_stream_copy_to_uint32_little_endian(
459
     ( (fsext_superblock_ext2_t *) data )->consistency_check_interval,
460
     value_32bit );
461
    libcnotify_printf(
462
     "%s: consistency check interval\t\t\t: %" PRIu32 "\n",
463
     function,
464
     value_32bit );
465
466
    byte_stream_copy_to_uint32_little_endian(
467
     ( (fsext_superblock_ext2_t *) data )->creator_operating_system,
468
     value_32bit );
469
    libcnotify_printf(
470
     "%s: creator operating system\t\t\t\t: %" PRIu32 " (%s)\n",
471
     function,
472
     value_32bit,
473
     libfsext_debug_print_creator_operating_system(
474
      value_32bit ) );
475
476
    libcnotify_printf(
477
     "%s: format revision\t\t\t\t\t: %" PRIu32 "\n",
478
     function,
479
     superblock->format_revision );
480
481
    byte_stream_copy_to_uint16_little_endian(
482
     ( (fsext_superblock_ext2_t *) data )->reserved_block_user_identifier,
483
     value_16bit );
484
    libcnotify_printf(
485
     "%s: reserved block user identifier\t\t\t: %" PRIu16 "\n",
486
     function,
487
     value_16bit );
488
489
    byte_stream_copy_to_uint16_little_endian(
490
     ( (fsext_superblock_ext2_t *) data )->reserved_block_group_identifier,
491
     value_16bit );
492
    libcnotify_printf(
493
     "%s: reserved block group identifier\t\t\t: %" PRIu16 "\n",
494
     function,
495
     value_16bit );
496
497
    libcnotify_printf(
498
     "\n" );
499
  }
500
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
501
502
9.11k
  if( superblock->block_size > ( 31 - 10 ) )
503
103
  {
504
103
    libcerror_error_set(
505
103
     error,
506
103
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
507
103
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
508
103
     "%s: invalid block size value out of bounds.",
509
103
     function );
510
511
103
    return( -1 );
512
103
  }
513
9.00k
  superblock->block_size = (uint32_t) ( 1024UL << superblock->block_size );
514
515
9.00k
  if( superblock->format_revision > 1 )
516
128
  {
517
128
    libcerror_error_set(
518
128
     error,
519
128
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
128
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
521
128
     "%s: unsupported format revision: %" PRIu32 ".",
522
128
     function,
523
128
     superblock->format_revision );
524
525
128
    return( -1 );
526
128
  }
527
/* TODO add sanity check of fragment size */
528
529
8.88k
  if( superblock->format_revision == 1 )
530
8.82k
  {
531
8.82k
    byte_stream_copy_to_uint16_little_endian(
532
8.82k
     ( (fsext_superblock_ext2_t *) data )->inode_size,
533
8.82k
     superblock->inode_size );
534
535
8.82k
    byte_stream_copy_to_uint16_little_endian(
536
8.82k
     ( (fsext_superblock_ext2_t *) data )->block_group,
537
8.82k
     superblock->block_group );
538
539
8.82k
    byte_stream_copy_to_uint32_little_endian(
540
8.82k
     ( (fsext_superblock_ext2_t *) data )->compatible_features_flags,
541
8.82k
     superblock->compatible_features_flags );
542
543
8.82k
    byte_stream_copy_to_uint32_little_endian(
544
8.82k
     ( (fsext_superblock_ext2_t *) data )->incompatible_features_flags,
545
8.82k
     superblock->incompatible_features_flags );
546
547
8.82k
    byte_stream_copy_to_uint32_little_endian(
548
8.82k
     ( (fsext_superblock_ext2_t *) data )->read_only_compatible_features_flags,
549
8.82k
     superblock->read_only_compatible_features_flags );
550
551
8.82k
    if( memory_copy(
552
8.82k
         superblock->file_system_identifier,
553
8.82k
         ( (fsext_superblock_ext2_t *) data )->file_system_identifier,
554
8.82k
         16 ) == NULL )
555
0
    {
556
0
      libcerror_error_set(
557
0
       error,
558
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
559
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
560
0
       "%s: unable to copy file system identifier.",
561
0
       function );
562
563
0
      return( -1 );
564
0
    }
565
8.82k
    if( memory_copy(
566
8.82k
         superblock->volume_label,
567
8.82k
         ( (fsext_superblock_ext2_t *) data )->volume_label,
568
8.82k
         16 ) == NULL )
569
0
    {
570
0
      libcerror_error_set(
571
0
       error,
572
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
573
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
574
0
       "%s: unable to copy volume label.",
575
0
       function );
576
577
0
      return( -1 );
578
0
    }
579
8.82k
    if( memory_copy(
580
8.82k
         superblock->last_mount_path,
581
8.82k
         ( (fsext_superblock_ext2_t *) data )->last_mount_path,
582
8.82k
         64 ) == NULL )
583
0
    {
584
0
      libcerror_error_set(
585
0
       error,
586
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
587
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
588
0
       "%s: unable to copy last mount path.",
589
0
       function );
590
591
0
      return( -1 );
592
0
    }
593
#if defined( HAVE_DEBUG_OUTPUT )
594
    if( libcnotify_verbose != 0 )
595
    {
596
      byte_stream_copy_to_uint32_little_endian(
597
       ( (fsext_superblock_ext2_t *) data )->first_non_reserved_inode,
598
       value_32bit );
599
      libcnotify_printf(
600
       "%s: first non-reserved inode\t\t\t\t: %" PRIu32 "\n",
601
       function,
602
       value_32bit );
603
604
      libcnotify_printf(
605
       "%s: inode size\t\t\t\t\t: %" PRIu16 "\n",
606
       function,
607
       superblock->inode_size );
608
609
      libcnotify_printf(
610
       "%s: block group\t\t\t\t\t: %" PRIu16 "\n",
611
       function,
612
       superblock->block_group );
613
614
      libcnotify_printf(
615
       "%s: compatible features flags\t\t\t: 0x%08" PRIx32 "\n",
616
       function,
617
       superblock->compatible_features_flags );
618
      libfsext_debug_print_compatible_features_flags(
619
       superblock->compatible_features_flags );
620
      libcnotify_printf(
621
       "\n" );
622
623
      libcnotify_printf(
624
       "%s: incompatible features flags\t\t\t: 0x%08" PRIx32 "\n",
625
       function,
626
       superblock->incompatible_features_flags );
627
      libfsext_debug_print_incompatible_features_flags(
628
       superblock->incompatible_features_flags );
629
      libcnotify_printf(
630
       "\n" );
631
632
      libcnotify_printf(
633
       "%s: read-only compatible features flags\t\t: 0x%08" PRIx32 "\n",
634
       function,
635
       superblock->read_only_compatible_features_flags );
636
      libfsext_debug_print_read_only_compatible_features_flags(
637
       superblock->read_only_compatible_features_flags );
638
      libcnotify_printf(
639
       "\n" );
640
641
      if( libfsext_debug_print_guid_value(
642
           function,
643
           "file system identifier\t\t\t\t",
644
           ( (fsext_superblock_ext2_t *) data )->file_system_identifier,
645
           16,
646
           LIBFGUID_ENDIAN_BIG,
647
           LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
648
           error ) != 1 )
649
      {
650
        libcerror_error_set(
651
         error,
652
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
653
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
654
         "%s: unable to print GUID value.",
655
         function );
656
657
        return( -1 );
658
      }
659
      if( libfsext_debug_print_utf8_string_value(
660
           function,
661
           "volume label\t\t\t\t\t",
662
           superblock->volume_label,
663
           16,
664
           error ) != 1 )
665
      {
666
        libcerror_error_set(
667
         error,
668
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
669
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
670
         "%s: unable to print UTF-8 string value.",
671
         function );
672
673
        return( -1 );
674
      }
675
      if( libfsext_debug_print_utf8_string_value(
676
           function,
677
           "last mount path\t\t\t\t\t",
678
           superblock->last_mount_path,
679
           64,
680
           error ) != 1 )
681
      {
682
        libcerror_error_set(
683
         error,
684
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
685
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
686
         "%s: unable to print UTF-8 string value.",
687
         function );
688
689
        return( -1 );
690
      }
691
      byte_stream_copy_to_uint32_little_endian(
692
       ( (fsext_superblock_ext2_t *) data )->algorithm_usage_bitmap,
693
       value_32bit );
694
      libcnotify_printf(
695
       "%s: algorithm usage bitmap\t\t\t\t: 0x%08" PRIx32 "\n",
696
       function,
697
       value_32bit );
698
699
      libcnotify_printf(
700
       "\n" );
701
    }
702
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
703
8.82k
  }
704
8.88k
  supported_feature_flags = 0x00000001UL
705
8.88k
                          | 0x00000004UL
706
8.88k
                          | 0x00000008UL
707
8.88k
                          | 0x00000010UL
708
8.88k
                          | 0x00000020UL
709
8.88k
                          | 0x00001000UL;
710
711
8.88k
  if( ( superblock->compatible_features_flags & ~( supported_feature_flags ) ) != 0 )
712
83
  {
713
83
    libcerror_error_set(
714
83
     error,
715
83
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
716
83
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
717
83
     "%s: unsupported compatible features flags: 0x%08" PRIx32 ".",
718
83
     function,
719
83
     superblock->compatible_features_flags );
720
721
83
    return( -1 );
722
83
  }
723
8.79k
  supported_feature_flags = 0x00000002UL
724
8.79k
                          | 0x00000004UL
725
8.79k
                          | 0x00000008UL
726
8.79k
                          | 0x00000010UL
727
8.79k
                          | 0x00000040UL
728
8.79k
                          | 0x00000080UL
729
8.79k
                          | 0x00000200UL
730
8.79k
                          | 0x00000400UL
731
8.79k
                          | 0x00008000UL
732
8.79k
                          | 0x00002000UL
733
8.79k
                          | 0x00010000UL
734
8.79k
                          | 0x00020000UL;
735
736
8.79k
  if( ( superblock->incompatible_features_flags & ~( supported_feature_flags ) ) != 0 )
737
70
  {
738
70
    libcerror_error_set(
739
70
     error,
740
70
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
741
70
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
742
70
     "%s: unsupported incompatible features flags: 0x%08" PRIx32 ".",
743
70
     function,
744
70
     superblock->incompatible_features_flags );
745
746
70
    return( -1 );
747
70
  }
748
8.72k
  if( ( ( superblock->compatible_features_flags & 0x00000200UL ) != 0 )
749
8.72k
   || ( ( superblock->incompatible_features_flags & 0x0001f7c0UL ) != 0 )
750
4.76k
   || ( ( superblock->read_only_compatible_features_flags & 0x00000378UL ) != 0 ) )
751
6.48k
  {
752
6.48k
    superblock->format_version = 4;
753
6.48k
  }
754
2.24k
  else if( ( ( superblock->compatible_features_flags & 0x00000004UL ) != 0 )
755
1.31k
        || ( ( superblock->incompatible_features_flags & 0x0000000cUL ) != 0 ) )
756
1.33k
  {
757
1.33k
    superblock->format_version = 3;
758
1.33k
  }
759
915
  else
760
915
  {
761
915
    superblock->format_version = 2;
762
915
  }
763
8.72k
  if( ( superblock->compatible_features_flags & 0x00000001UL ) != 0 )
764
537
  {
765
#if defined( HAVE_DEBUG_OUTPUT )
766
    if( libcnotify_verbose != 0 )
767
    {
768
      libcnotify_printf(
769
       "%s: number of pre-allocated blocks per file\t\t: %" PRIu8 "\n",
770
       function,
771
       ( (fsext_superblock_ext2_t *) data )->number_of_pre_allocated_blocks_per_file );
772
773
      libcnotify_printf(
774
       "%s: number of pre-allocated blocks per directory\t\t: %" PRIu8 "\n",
775
       function,
776
       ( (fsext_superblock_ext2_t *) data )->number_of_pre_allocated_blocks_per_directory );
777
778
      libcnotify_printf(
779
       "%s: padding1:\n",
780
       function );
781
      libcnotify_print_data(
782
       ( (fsext_superblock_ext2_t *) data )->padding1,
783
       2,
784
       0 );
785
    }
786
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
787
537
  }
788
8.72k
  if( superblock->format_version == 4 )
789
6.48k
  {
790
6.48k
    byte_stream_copy_to_uint16_little_endian(
791
6.48k
     ( (fsext_superblock_ext4_t *) data )->group_descriptor_size,
792
6.48k
     superblock->group_descriptor_size );
793
6.48k
  }
794
8.72k
  byte_stream_copy_to_uint32_little_endian(
795
8.72k
   ( (fsext_superblock_ext2_t *) data )->first_metadata_block_group,
796
8.72k
   superblock->first_metadata_block_group );
797
798
8.72k
  if( superblock->format_version == 4 )
799
6.48k
  {
800
6.48k
    number_of_block_groups_per_flex_group = ( (fsext_superblock_ext4_t *) data )->number_of_block_groups_per_flex_group;
801
802
6.48k
    checksum_type = ( (fsext_superblock_ext4_t *) data )->checksum_type;
803
804
6.48k
    byte_stream_copy_to_uint32_little_endian(
805
6.48k
     ( (fsext_superblock_ext4_t *) data )->file_system_creation_time,
806
6.48k
     superblock->file_system_creation_time );
807
808
6.48k
    byte_stream_copy_to_uint32_little_endian(
809
6.48k
     ( (fsext_superblock_ext4_t *) data )->metadata_checksum_seed,
810
6.48k
     superblock->metadata_checksum_seed );
811
6.48k
  }
812
#if defined( HAVE_DEBUG_OUTPUT )
813
  if( libcnotify_verbose != 0 )
814
  {
815
    if( libfsext_debug_print_guid_value(
816
         function,
817
         "journal identifier\t\t\t\t",
818
         ( (fsext_superblock_ext2_t *) data )->journal_identifier,
819
         16,
820
         LIBFGUID_ENDIAN_BIG,
821
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
822
         error ) != 1 )
823
    {
824
      libcerror_error_set(
825
       error,
826
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
827
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
828
       "%s: unable to print GUID value.",
829
       function );
830
831
      return( -1 );
832
    }
833
    byte_stream_copy_to_uint32_little_endian(
834
     ( (fsext_superblock_ext2_t *) data )->journal_inode_number,
835
     value_32bit );
836
    libcnotify_printf(
837
     "%s: journal inode number\t\t\t\t: %" PRIu32 "\n",
838
     function,
839
     value_32bit );
840
841
    byte_stream_copy_to_uint32_little_endian(
842
     ( (fsext_superblock_ext2_t *) data )->journal_device,
843
     value_32bit );
844
    libcnotify_printf(
845
     "%s: journal device\t\t\t\t\t: %" PRIu32 "\n",
846
     function,
847
     value_32bit );
848
849
    byte_stream_copy_to_uint32_little_endian(
850
     ( (fsext_superblock_ext2_t *) data )->orphan_inode_list_head,
851
     value_32bit );
852
    libcnotify_printf(
853
     "%s: orphan inode list head\t\t\t\t: %" PRIu32 "\n",
854
     function,
855
     value_32bit );
856
857
    libcnotify_printf(
858
     "%s: HTREE hash seed:\n",
859
     function );
860
    libcnotify_print_data(
861
     ( (fsext_superblock_ext2_t *) data )->htree_hash_seed,
862
     16,
863
     0 );
864
865
    libcnotify_printf(
866
     "%s: default hash version\t\t\t\t: %" PRIu8 "\n",
867
     function,
868
     ( (fsext_superblock_ext2_t *) data )->default_hash_version );
869
870
    if( superblock->format_version < 4 )
871
    {
872
      libcnotify_printf(
873
       "%s: padding2:\n",
874
       function );
875
      libcnotify_print_data(
876
       ( (fsext_superblock_ext2_t *) data )->padding2,
877
       3,
878
       0 );
879
    }
880
    else
881
    {
882
      libcnotify_printf(
883
       "%s: journal backup type\t\t\t\t: %" PRIu8 "\n",
884
       function,
885
       ( (fsext_superblock_ext4_t *) data )->journal_backup_type );
886
887
      libcnotify_printf(
888
       "%s: group descriptor size\t\t\t\t: %" PRIu16 "\n",
889
       function,
890
       superblock->group_descriptor_size );
891
    }
892
    byte_stream_copy_to_uint32_little_endian(
893
     ( (fsext_superblock_ext2_t *) data )->default_mount_options,
894
     value_32bit );
895
    libcnotify_printf(
896
     "%s: default mount options\t\t\t\t: %" PRIu32 "\n",
897
     function,
898
     value_32bit );
899
900
    libcnotify_printf(
901
     "%s: first metadata block group\t\t\t: %" PRIu32 "\n",
902
     function,
903
     superblock->first_metadata_block_group );
904
905
    if( superblock->format_version == 4 )
906
    {
907
      if( libfsext_debug_print_posix_time_value(
908
           function,
909
           "file system creation time\t\t\t",
910
           ( (fsext_superblock_ext4_t *) data )->file_system_creation_time,
911
           4,
912
           LIBFDATETIME_ENDIAN_LITTLE,
913
           LIBFDATETIME_POSIX_TIME_VALUE_TYPE_SECONDS_32BIT_SIGNED,
914
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
915
           error ) != 1 )
916
      {
917
        libcerror_error_set(
918
         error,
919
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
920
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
921
         "%s: unable to print posix time value.",
922
         function );
923
924
        return( -1 );
925
      }
926
      libcnotify_printf(
927
       "%s: backup journal inodes:\n",
928
       function );
929
      libcnotify_print_data(
930
       ( (fsext_superblock_ext4_t *) data )->backup_journal_inodes,
931
       68,
932
       0 );
933
934
      byte_stream_copy_to_uint32_little_endian(
935
       ( (fsext_superblock_ext4_t *) data )->number_of_blocks_upper,
936
       value_32bit );
937
      libcnotify_printf(
938
       "%s: number of blocks (upper 32-bit)\t\t\t: %" PRIu32 "\n",
939
       function,
940
       value_32bit );
941
942
      byte_stream_copy_to_uint32_little_endian(
943
       ( (fsext_superblock_ext4_t *) data )->number_of_reserved_blocks_upper,
944
       value_32bit );
945
      libcnotify_printf(
946
       "%s: number of reserved blocks (upper 32-bit)\t\t: %" PRIu32 "\n",
947
       function,
948
       value_32bit );
949
950
      byte_stream_copy_to_uint32_little_endian(
951
       ( (fsext_superblock_ext4_t *) data )->number_of_unallocated_blocks_upper,
952
       value_32bit );
953
      libcnotify_printf(
954
       "%s: number of unallocated blocks (upper 32-bit)\t: %" PRIu32 "\n",
955
       function,
956
       value_32bit );
957
958
      byte_stream_copy_to_uint16_little_endian(
959
       ( (fsext_superblock_ext4_t *) data )->minimum_inode_size,
960
       value_16bit );
961
      libcnotify_printf(
962
       "%s: minimum inode size\t\t\t\t: %" PRIu16 "\n",
963
       function,
964
       value_16bit );
965
966
      byte_stream_copy_to_uint16_little_endian(
967
       ( (fsext_superblock_ext4_t *) data )->reserved_inode_size,
968
       value_16bit );
969
      libcnotify_printf(
970
       "%s: reserved inode size\t\t\t\t: %" PRIu16 "\n",
971
       function,
972
       value_16bit );
973
974
      byte_stream_copy_to_uint32_little_endian(
975
       ( (fsext_superblock_ext4_t *) data )->flags,
976
       value_32bit );
977
      libcnotify_printf(
978
       "%s: flags\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
979
       function,
980
       value_32bit );
981
982
      byte_stream_copy_to_uint16_little_endian(
983
       ( (fsext_superblock_ext4_t *) data )->read_stride,
984
       value_16bit );
985
      libcnotify_printf(
986
       "%s: read stride\t\t\t\t\t: %" PRIu16 "\n",
987
       function,
988
       value_16bit );
989
990
      byte_stream_copy_to_uint16_little_endian(
991
       ( (fsext_superblock_ext4_t *) data )->multi_mount_protection_update_interval,
992
       value_16bit );
993
      libcnotify_printf(
994
       "%s: multi-mount protection update interval\t\t: %" PRIu16 "\n",
995
       function,
996
       value_16bit );
997
998
      byte_stream_copy_to_uint64_little_endian(
999
       ( (fsext_superblock_ext4_t *) data )->multi_mount_protection_block,
1000
       value_64bit );
1001
      libcnotify_printf(
1002
       "%s: multi-mount protection block\t\t\t: %" PRIu64 "\n",
1003
       function,
1004
       value_64bit );
1005
1006
      byte_stream_copy_to_uint32_little_endian(
1007
       ( (fsext_superblock_ext4_t *) data )->raid_stripe_width,
1008
       value_32bit );
1009
      libcnotify_printf(
1010
       "%s: RAID stripe width\t\t\t\t: %" PRIu32 "\n",
1011
       function,
1012
       value_32bit );
1013
1014
      libcnotify_printf(
1015
       "%s: number of blocks per flex group\t\t\t: %" PRIu32 " (2 ^ %" PRIu8 ")\n",
1016
       function,
1017
       (uint64_t) 1 << number_of_block_groups_per_flex_group,
1018
       number_of_block_groups_per_flex_group );
1019
1020
      libcnotify_printf(
1021
       "%s: checksum type\t\t\t\t\t: %" PRIu8 "\n",
1022
       function,
1023
       ( (fsext_superblock_ext4_t *) data )->checksum_type );
1024
1025
      libcnotify_printf(
1026
       "%s: encryption level\t\t\t\t\t: %" PRIu8 "\n",
1027
       function,
1028
       ( (fsext_superblock_ext4_t *) data )->encryption_level );
1029
1030
      libcnotify_printf(
1031
       "%s: padding2\t\t\t\t\t\t: 0x%02" PRIx8 "\n",
1032
       function,
1033
       ( (fsext_superblock_ext4_t *) data )->padding2 );
1034
1035
      byte_stream_copy_to_uint64_little_endian(
1036
       ( (fsext_superblock_ext4_t *) data )->write_count,
1037
       value_64bit );
1038
      libcnotify_printf(
1039
       "%s: write count\t\t\t\t\t: %" PRIu64 "\n",
1040
       function,
1041
       value_64bit );
1042
1043
      byte_stream_copy_to_uint32_little_endian(
1044
       ( (fsext_superblock_ext4_t *) data )->snapshot_inode_number,
1045
       value_32bit );
1046
      libcnotify_printf(
1047
       "%s: snapshot inode number\t\t\t\t: %" PRIu32 "\n",
1048
       function,
1049
       value_32bit );
1050
1051
      byte_stream_copy_to_uint32_little_endian(
1052
       ( (fsext_superblock_ext4_t *) data )->snapshot_sequential_identifier,
1053
       value_32bit );
1054
      libcnotify_printf(
1055
       "%s: snapshot sequential identifier\t\t\t: %" PRIu32 "\n",
1056
       function,
1057
       value_32bit );
1058
1059
      byte_stream_copy_to_uint64_little_endian(
1060
       ( (fsext_superblock_ext4_t *) data )->snapshot_number_of_reserved_blocks,
1061
       value_64bit );
1062
      libcnotify_printf(
1063
       "%s: snapshot number of reserved blocks\t\t: %" PRIu64 "\n",
1064
       function,
1065
       value_64bit );
1066
1067
      byte_stream_copy_to_uint32_little_endian(
1068
       ( (fsext_superblock_ext4_t *) data )->snapshot_inode_list,
1069
       value_32bit );
1070
      libcnotify_printf(
1071
       "%s: snapshot inode list\t\t\t\t: %" PRIu32 "\n",
1072
       function,
1073
       value_32bit );
1074
1075
      byte_stream_copy_to_uint32_little_endian(
1076
       ( (fsext_superblock_ext4_t *) data )->number_of_errors,
1077
       value_32bit );
1078
      libcnotify_printf(
1079
       "%s: number of errors\t\t\t\t\t: %" PRIu32 "\n",
1080
       function,
1081
       value_32bit );
1082
1083
      byte_stream_copy_to_uint32_little_endian(
1084
       ( (fsext_superblock_ext4_t *) data )->first_error_time,
1085
       value_32bit );
1086
      libcnotify_printf(
1087
       "%s: first error time\t\t\t\t\t: %" PRIu32 "\n",
1088
       function,
1089
       value_32bit );
1090
1091
      byte_stream_copy_to_uint32_little_endian(
1092
       ( (fsext_superblock_ext4_t *) data )->first_error_inode_number,
1093
       value_32bit );
1094
      libcnotify_printf(
1095
       "%s: first error inode number\t\t\t\t: %" PRIu32 "\n",
1096
       function,
1097
       value_32bit );
1098
1099
      byte_stream_copy_to_uint32_little_endian(
1100
       ( (fsext_superblock_ext4_t *) data )->first_error_block_number,
1101
       value_32bit );
1102
      libcnotify_printf(
1103
       "%s: first error block number\t\t\t\t: %" PRIu32 "\n",
1104
       function,
1105
       value_32bit );
1106
1107
      libcnotify_printf(
1108
       "%s: first error function:\n",
1109
       function );
1110
      libcnotify_print_data(
1111
       ( (fsext_superblock_ext4_t *) data )->first_error_function,
1112
       32,
1113
       0 );
1114
1115
      byte_stream_copy_to_uint32_little_endian(
1116
       ( (fsext_superblock_ext4_t *) data )->first_error_function_line_number,
1117
       value_32bit );
1118
      libcnotify_printf(
1119
       "%s: first error function line number\t\t\t: %" PRIu32 "\n",
1120
       function,
1121
       value_32bit );
1122
1123
      byte_stream_copy_to_uint32_little_endian(
1124
       ( (fsext_superblock_ext4_t *) data )->last_error_time,
1125
       value_32bit );
1126
      libcnotify_printf(
1127
       "%s: last error time\t\t\t\t\t: %" PRIu32 "\n",
1128
       function,
1129
       value_32bit );
1130
1131
      byte_stream_copy_to_uint32_little_endian(
1132
       ( (fsext_superblock_ext4_t *) data )->last_error_inode_number,
1133
       value_32bit );
1134
      libcnotify_printf(
1135
       "%s: last error inode number\t\t\t\t: %" PRIu32 "\n",
1136
       function,
1137
       value_32bit );
1138
1139
      byte_stream_copy_to_uint32_little_endian(
1140
       ( (fsext_superblock_ext4_t *) data )->last_error_function_line_number,
1141
       value_32bit );
1142
      libcnotify_printf(
1143
       "%s: last error function line number\t\t\t: %" PRIu32 "\n",
1144
       function,
1145
       value_32bit );
1146
1147
      byte_stream_copy_to_uint32_little_endian(
1148
       ( (fsext_superblock_ext4_t *) data )->last_error_block_number,
1149
       value_32bit );
1150
      libcnotify_printf(
1151
       "%s: last error block number\t\t\t\t: %" PRIu32 "\n",
1152
       function,
1153
       value_32bit );
1154
1155
      libcnotify_printf(
1156
       "%s: last error function:\n",
1157
       function );
1158
      libcnotify_print_data(
1159
       ( (fsext_superblock_ext4_t *) data )->last_error_function,
1160
       32,
1161
       0 );
1162
1163
      libcnotify_printf(
1164
       "%s: mount options:\n",
1165
       function );
1166
      libcnotify_print_data(
1167
       ( (fsext_superblock_ext4_t *) data )->last_error_function,
1168
       64,
1169
       0 );
1170
1171
      byte_stream_copy_to_uint32_little_endian(
1172
       ( (fsext_superblock_ext4_t *) data )->user_quota_inode_number,
1173
       value_32bit );
1174
      libcnotify_printf(
1175
       "%s: user quota inode number\t\t\t\t: %" PRIu32 "\n",
1176
       function,
1177
       value_32bit );
1178
1179
      byte_stream_copy_to_uint32_little_endian(
1180
       ( (fsext_superblock_ext4_t *) data )->group_quota_inode_number,
1181
       value_32bit );
1182
      libcnotify_printf(
1183
       "%s: group quota inode number\t\t\t\t: %" PRIu32 "\n",
1184
       function,
1185
       value_32bit );
1186
1187
      byte_stream_copy_to_uint32_little_endian(
1188
       ( (fsext_superblock_ext4_t *) data )->overhead_number_of_clusters,
1189
       value_32bit );
1190
      libcnotify_printf(
1191
       "%s: overhead number of clusters\t\t\t: %" PRIu32 "\n",
1192
       function,
1193
       value_32bit );
1194
1195
      byte_stream_copy_to_uint32_little_endian(
1196
       ( (fsext_superblock_ext4_t *) data )->backup_block_group1,
1197
       value_32bit );
1198
      libcnotify_printf(
1199
       "%s: first backup block group\t\t\t\t: %" PRIu32 "\n",
1200
       function,
1201
       value_32bit );
1202
1203
      byte_stream_copy_to_uint32_little_endian(
1204
       ( (fsext_superblock_ext4_t *) data )->backup_block_group2,
1205
       value_32bit );
1206
      libcnotify_printf(
1207
       "%s: second backup block group\t\t\t: %" PRIu32 "\n",
1208
       function,
1209
       value_32bit );
1210
1211
      byte_stream_copy_to_uint32_little_endian(
1212
       ( (fsext_superblock_ext4_t *) data )->encryption_algorithms,
1213
       value_32bit );
1214
      libcnotify_printf(
1215
       "%s: encryption algorithms\t\t\t\t: %" PRIu32 "\n",
1216
       function,
1217
       value_32bit );
1218
1219
      libcnotify_printf(
1220
       "%s: encryption password salt:\n",
1221
       function );
1222
      libcnotify_print_data(
1223
       ( (fsext_superblock_ext4_t *) data )->encryption_password_salt,
1224
       16,
1225
       0 );
1226
1227
      byte_stream_copy_to_uint32_little_endian(
1228
       ( (fsext_superblock_ext4_t *) data )->lost_and_found_inode_number,
1229
       value_32bit );
1230
      libcnotify_printf(
1231
       "%s: lost and found inode inode number\t\t: %" PRIu32 "\n",
1232
       function,
1233
       value_32bit );
1234
1235
      byte_stream_copy_to_uint32_little_endian(
1236
       ( (fsext_superblock_ext4_t *) data )->project_quota_inode_number,
1237
       value_32bit );
1238
      libcnotify_printf(
1239
       "%s: project quota inode number\t\t\t: %" PRIu32 "\n",
1240
       function,
1241
       value_32bit );
1242
1243
      libcnotify_printf(
1244
       "%s: metadata checksum seed\t\t\t\t: 0x%08" PRIx32 "\n",
1245
       function,
1246
       superblock->metadata_checksum_seed );
1247
1248
      libcnotify_printf(
1249
       "%s: unknown1:\n",
1250
       function );
1251
      libcnotify_print_data(
1252
       ( (fsext_superblock_ext4_t *) data )->unknown1,
1253
       8,
1254
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1255
1256
      byte_stream_copy_to_uint16_little_endian(
1257
       ( (fsext_superblock_ext4_t *) data )->encoding,
1258
       value_16bit );
1259
      libcnotify_printf(
1260
       "%s: encoding\t\t\t\t\t\t: %" PRIu16 "\n",
1261
       function,
1262
       value_16bit );
1263
1264
      byte_stream_copy_to_uint16_little_endian(
1265
       ( (fsext_superblock_ext4_t *) data )->encoding_flags,
1266
       value_16bit );
1267
      libcnotify_printf(
1268
       "%s: encoding flags\t\t\t\t\t: 0x%04" PRIx16 "\n",
1269
       function,
1270
       value_16bit );
1271
1272
      byte_stream_copy_to_uint32_little_endian(
1273
       ( (fsext_superblock_ext4_t *) data )->orphan_file_inode_number,
1274
       value_32bit );
1275
      libcnotify_printf(
1276
       "%s: orphan file inode number\t\t\t\t: %" PRIu32 "\n",
1277
       function,
1278
       value_32bit );
1279
    }
1280
    libcnotify_printf(
1281
     "%s: padding3:\n",
1282
     function );
1283
1284
    if( superblock->format_version < 4 )
1285
    {
1286
      libcnotify_print_data(
1287
       ( (fsext_superblock_ext2_t *) data )->padding3,
1288
       190,
1289
       0 );
1290
    }
1291
    else
1292
    {
1293
      libcnotify_print_data(
1294
       ( (fsext_superblock_ext4_t *) data )->padding3,
1295
       376,
1296
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1297
    }
1298
    if( superblock->format_version == 4 )
1299
    {
1300
      byte_stream_copy_to_uint32_little_endian(
1301
       ( (fsext_superblock_ext4_t *) data )->checksum,
1302
       stored_checksum );
1303
      libcnotify_printf(
1304
       "%s: checksum\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
1305
       function,
1306
       stored_checksum );
1307
1308
      libcnotify_printf(
1309
       "\n" );
1310
    }
1311
  }
1312
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1313
1314
8.72k
  if( ( superblock->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 )
1315
675
  {
1316
675
    if( checksum_type != 1 )
1317
26
    {
1318
26
      libcerror_error_set(
1319
26
       error,
1320
26
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1321
26
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1322
26
       "%s: unsupported checksum type: %" PRIu8 ".",
1323
26
       function,
1324
26
       checksum_type );
1325
1326
26
      return( -1 );
1327
26
    }
1328
649
    if( libfsext_checksum_calculate_crc32(
1329
649
         &calculated_checksum,
1330
649
         data,
1331
649
         data_size - 4,
1332
649
         0,
1333
649
         error ) != 1 )
1334
0
    {
1335
0
      libcerror_error_set(
1336
0
       error,
1337
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1338
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1339
0
       "%s: unable to calculate CRC-32.",
1340
0
       function );
1341
1342
0
      return( -1 );
1343
0
    }
1344
649
    calculated_checksum = 0xffffffffUL - calculated_checksum;
1345
1346
649
    if( ( stored_checksum != 0 )
1347
0
     && ( stored_checksum != calculated_checksum ) )
1348
0
    {
1349
#if defined( HAVE_DEBUG_OUTPUT )
1350
      if( libcnotify_verbose != 0 )
1351
      {
1352
        libcnotify_printf(
1353
         "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
1354
         function,
1355
         stored_checksum,
1356
         calculated_checksum );
1357
      }
1358
#endif
1359
0
      superblock->is_corrupt = 1;
1360
0
    }
1361
649
  }
1362
8.70k
  if( superblock->number_of_blocks == 0 )
1363
4
  {
1364
4
    libcerror_error_set(
1365
4
     error,
1366
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1367
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1368
4
     "%s: invalid number of blocks value out of bounds.",
1369
4
     function );
1370
1371
4
    return( -1 );
1372
4
  }
1373
8.69k
  if( superblock->number_of_blocks_per_block_group == 0 )
1374
4
  {
1375
4
    libcerror_error_set(
1376
4
     error,
1377
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1378
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1379
4
     "%s: invalid number of blocks per block group value out of bounds.",
1380
4
     function );
1381
1382
4
    return( -1 );
1383
4
  }
1384
8.69k
  superblock->number_of_block_groups = superblock->number_of_blocks / superblock->number_of_blocks_per_block_group;
1385
1386
8.69k
  if( ( superblock->number_of_blocks % superblock->number_of_blocks_per_block_group ) != 0 )
1387
7.95k
  {
1388
7.95k
    superblock->number_of_block_groups += 1;
1389
7.95k
  }
1390
8.69k
  if( superblock->number_of_blocks_per_block_group > ( (uint64_t) UINT64_MAX / superblock->block_size ) )
1391
0
  {
1392
0
    libcerror_error_set(
1393
0
     error,
1394
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1395
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1396
0
     "%s: invalid number of blocks per flex group value out of bounds.",
1397
0
     function );
1398
1399
0
    return( -1 );
1400
0
  }
1401
8.69k
  superblock->block_group_size = superblock->number_of_blocks_per_block_group * superblock->block_size;
1402
1403
8.69k
  if( number_of_block_groups_per_flex_group > 0 )
1404
1.02k
  {
1405
1.02k
    if( number_of_block_groups_per_flex_group >= 16 )
1406
35
    {
1407
35
      libcerror_error_set(
1408
35
       error,
1409
35
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1410
35
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1411
35
       "%s: invalid number of block groups per flex group value out of bounds.",
1412
35
       function );
1413
1414
35
      return( -1 );
1415
35
    }
1416
991
    superblock->number_of_blocks_per_flex_group = (uint32_t) 1 << number_of_block_groups_per_flex_group;
1417
1418
991
    if( superblock->number_of_blocks_per_flex_group > ( (uint32_t) UINT32_MAX / superblock->number_of_blocks_per_block_group ) )
1419
35
    {
1420
35
      libcerror_error_set(
1421
35
       error,
1422
35
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1423
35
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1424
35
       "%s: invalid number of block groups per flex group value out of bounds.",
1425
35
       function );
1426
1427
35
      return( -1 );
1428
35
    }
1429
956
    superblock->number_of_blocks_per_flex_group *= superblock->number_of_blocks_per_block_group;
1430
1431
956
    if( superblock->number_of_blocks_per_flex_group > ( (uint64_t) UINT64_MAX / superblock->block_size ) )
1432
0
    {
1433
0
      libcerror_error_set(
1434
0
       error,
1435
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1436
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1437
0
       "%s: invalid number of blocks per flex group value out of bounds.",
1438
0
       function );
1439
1440
0
      return( -1 );
1441
0
    }
1442
956
    superblock->flex_group_size = superblock->number_of_blocks_per_flex_group * superblock->block_size;
1443
956
  }
1444
#if defined( HAVE_DEBUG_OUTPUT )
1445
  if( libcnotify_verbose != 0 )
1446
  {
1447
    libcnotify_printf(
1448
     "%s: format version\t\t\t\t\t: %" PRIu32 "\n",
1449
     function,
1450
     superblock->format_version );
1451
1452
    libcnotify_printf(
1453
     "%s: number of blocks per block group\t\t\t: %" PRIu64 "\n",
1454
     function,
1455
     superblock->number_of_blocks_per_block_group );
1456
1457
    libcnotify_printf(
1458
     "%s: block group size\t\t\t\t\t: %" PRIu64 "\n",
1459
     function,
1460
     superblock->block_group_size );
1461
1462
    libcnotify_printf(
1463
     "%s: number of blocks per flex group\t\t\t: %" PRIu64 "\n",
1464
     function,
1465
     superblock->number_of_blocks_per_flex_group );
1466
1467
    libcnotify_printf(
1468
     "%s: flex group size\t\t\t\t\t: %" PRIu64 "\n",
1469
     function,
1470
     superblock->flex_group_size );
1471
1472
    libcnotify_printf(
1473
     "%s: number of block groups\t\t\t\t: %" PRIu32 "\n",
1474
     function,
1475
     superblock->number_of_block_groups );
1476
1477
    libcnotify_printf(
1478
     "\n" );
1479
  }
1480
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1481
1482
8.62k
  return( 1 );
1483
8.69k
}
1484
1485
/* Reads the superblock from a Basic File IO (bfio) handle
1486
 * Returns 1 if successful, 0 if signature does not match or -1 on error
1487
 */
1488
int libfsext_superblock_read_file_io_handle(
1489
     libfsext_superblock_t *superblock,
1490
     libbfio_handle_t *file_io_handle,
1491
     off64_t file_offset,
1492
     libcerror_error_t **error )
1493
9.62k
{
1494
9.62k
  uint8_t data[ 1024 ];
1495
1496
9.62k
  static char *function = "libfsext_superblock_read_file_io_handle";
1497
9.62k
  ssize_t read_count    = 0;
1498
9.62k
  int result            = 0;
1499
1500
#if defined( HAVE_DEBUG_OUTPUT )
1501
  if( libcnotify_verbose != 0 )
1502
  {
1503
    libcnotify_printf(
1504
     "%s: reading superblock at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1505
     function,
1506
     file_offset,
1507
     file_offset );
1508
  }
1509
#endif
1510
9.62k
  read_count = libbfio_handle_read_buffer_at_offset(
1511
9.62k
                file_io_handle,
1512
9.62k
                data,
1513
9.62k
                1024,
1514
9.62k
                file_offset,
1515
9.62k
                error );
1516
1517
9.62k
  if( read_count != (ssize_t) 1024 )
1518
214
  {
1519
214
    libcerror_error_set(
1520
214
     error,
1521
214
     LIBCERROR_ERROR_DOMAIN_IO,
1522
214
     LIBCERROR_IO_ERROR_READ_FAILED,
1523
214
     "%s: unable to read superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1524
214
     function,
1525
214
     file_offset,
1526
214
     file_offset );
1527
1528
214
    return( -1 );
1529
214
  }
1530
9.41k
  result = libfsext_superblock_read_data(
1531
9.41k
            superblock,
1532
9.41k
            data,
1533
9.41k
            1024,
1534
9.41k
            error );
1535
1536
9.41k
  if( result == -1 )
1537
488
  {
1538
488
    libcerror_error_set(
1539
488
     error,
1540
488
     LIBCERROR_ERROR_DOMAIN_IO,
1541
488
     LIBCERROR_IO_ERROR_READ_FAILED,
1542
488
     "%s: unable to read superblock at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1543
488
     function,
1544
488
     file_offset,
1545
488
     file_offset );
1546
1547
488
    return( -1 );
1548
488
  }
1549
8.92k
  return( result );
1550
9.41k
}
1551
1552
/* Retrieves the file system identifier
1553
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
1554
 * Returns 1 if successful or -1 on error
1555
 */
1556
int libfsext_superblock_get_file_system_identifier(
1557
     libfsext_superblock_t *superblock,
1558
     uint8_t *uuid_data,
1559
     size_t uuid_data_size,
1560
     libcerror_error_t **error )
1561
258
{
1562
258
  static char *function = "libfsext_superblock_get_file_system_identifier";
1563
1564
258
  if( superblock == NULL )
1565
0
  {
1566
0
    libcerror_error_set(
1567
0
     error,
1568
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1569
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1570
0
     "%s: invalid superblock.",
1571
0
     function );
1572
1573
0
    return( -1 );
1574
0
  }
1575
258
  if( uuid_data == NULL )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1580
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1581
0
     "%s: invalid UUID data.",
1582
0
     function );
1583
1584
0
    return( -1 );
1585
0
  }
1586
258
  if( ( uuid_data_size < 16 )
1587
258
   || ( uuid_data_size > (size_t) SSIZE_MAX ) )
1588
0
  {
1589
0
    libcerror_error_set(
1590
0
     error,
1591
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1592
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1593
0
     "%s: invalid UUID data size value out of bounds.",
1594
0
     function );
1595
1596
0
    return( -1 );
1597
0
  }
1598
258
  if( memory_copy(
1599
258
       uuid_data,
1600
258
       superblock->file_system_identifier,
1601
258
       16 ) == NULL )
1602
0
  {
1603
0
    libcerror_error_set(
1604
0
     error,
1605
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1606
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1607
0
     "%s: unable to copy file system identifier.",
1608
0
     function );
1609
1610
0
    return( -1 );
1611
0
  }
1612
258
  return( 1 );
1613
258
}
1614
1615
/* Retrieves the size of the UTF-8 encoded volume label
1616
 * The returned size includes the end of string character
1617
 * Returns 1 if successful, 0 if not available or -1 on error
1618
 */
1619
int libfsext_superblock_get_utf8_volume_label_size(
1620
     libfsext_superblock_t *superblock,
1621
     size_t *utf8_string_size,
1622
     libcerror_error_t **error )
1623
258
{
1624
258
  static char *function = "libfsext_superblock_get_utf8_volume_label_size";
1625
1626
258
  if( superblock == NULL )
1627
0
  {
1628
0
    libcerror_error_set(
1629
0
     error,
1630
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1631
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1632
0
     "%s: invalid superblock.",
1633
0
     function );
1634
1635
0
    return( -1 );
1636
0
  }
1637
258
  if( libuna_utf8_string_size_from_utf8_stream(
1638
258
       superblock->volume_label,
1639
258
       16,
1640
258
       utf8_string_size,
1641
258
       error ) != 1 )
1642
168
  {
1643
168
    libcerror_error_set(
1644
168
     error,
1645
168
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1646
168
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1647
168
     "%s: unable to retrieve UTF-8 string size.",
1648
168
     function );
1649
1650
168
    return( -1 );
1651
168
  }
1652
90
  return( 1 );
1653
258
}
1654
1655
/* Retrieves the UTF-8 encoded volume label
1656
 * The size should include the end of string character
1657
 * Returns 1 if successful, 0 if not available or -1 on error
1658
 */
1659
int libfsext_superblock_get_utf8_volume_label(
1660
     libfsext_superblock_t *superblock,
1661
     uint8_t *utf8_string,
1662
     size_t utf8_string_size,
1663
     libcerror_error_t **error )
1664
258
{
1665
258
  static char *function = "libfsext_superblock_get_utf8_volume_label";
1666
1667
258
  if( superblock == NULL )
1668
0
  {
1669
0
    libcerror_error_set(
1670
0
     error,
1671
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1672
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1673
0
     "%s: invalid superblock.",
1674
0
     function );
1675
1676
0
    return( -1 );
1677
0
  }
1678
258
  if( libuna_utf8_string_copy_from_utf8_stream(
1679
258
       utf8_string,
1680
258
       utf8_string_size,
1681
258
       superblock->volume_label,
1682
258
       16,
1683
258
       error ) != 1 )
1684
168
  {
1685
168
    libcerror_error_set(
1686
168
     error,
1687
168
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1688
168
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1689
168
     "%s: unable to retrieve UTF-8 string.",
1690
168
     function );
1691
1692
168
    return( -1 );
1693
168
  }
1694
90
  return( 1 );
1695
258
}
1696
1697
/* Retrieves the size of the UTF-16 encoded volume label
1698
 * The returned size includes the end of string character
1699
 * Returns 1 if successful, 0 if not available or -1 on error
1700
 */
1701
int libfsext_superblock_get_utf16_volume_label_size(
1702
     libfsext_superblock_t *superblock,
1703
     size_t *utf16_string_size,
1704
     libcerror_error_t **error )
1705
0
{
1706
0
  static char *function = "libfsext_superblock_get_utf16_volume_label_size";
1707
1708
0
  if( superblock == NULL )
1709
0
  {
1710
0
    libcerror_error_set(
1711
0
     error,
1712
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1713
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1714
0
     "%s: invalid superblock.",
1715
0
     function );
1716
1717
0
    return( -1 );
1718
0
  }
1719
0
  if( libuna_utf16_string_size_from_utf8_stream(
1720
0
       superblock->volume_label,
1721
0
       16,
1722
0
       utf16_string_size,
1723
0
       error ) != 1 )
1724
0
  {
1725
0
    libcerror_error_set(
1726
0
     error,
1727
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1728
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1729
0
     "%s: unable to retrieve UTF-16 string size.",
1730
0
     function );
1731
1732
0
    return( -1 );
1733
0
  }
1734
0
  return( 1 );
1735
0
}
1736
1737
/* Retrieves the UTF-16 encoded volume label
1738
 * The size should include the end of string character
1739
 * Returns 1 if successful, 0 if not available or -1 on error
1740
 */
1741
int libfsext_superblock_get_utf16_volume_label(
1742
     libfsext_superblock_t *superblock,
1743
     uint16_t *utf16_string,
1744
     size_t utf16_string_size,
1745
     libcerror_error_t **error )
1746
0
{
1747
0
  static char *function = "libfsext_superblock_get_utf16_volume_label";
1748
1749
0
  if( superblock == NULL )
1750
0
  {
1751
0
    libcerror_error_set(
1752
0
     error,
1753
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1754
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1755
0
     "%s: invalid superblock.",
1756
0
     function );
1757
1758
0
    return( -1 );
1759
0
  }
1760
0
  if( libuna_utf16_string_copy_from_utf8_stream(
1761
0
       utf16_string,
1762
0
       utf16_string_size,
1763
0
       superblock->volume_label,
1764
0
       16,
1765
0
       error ) != 1 )
1766
0
  {
1767
0
    libcerror_error_set(
1768
0
     error,
1769
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1770
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1771
0
     "%s: unable to retrieve UTF-16 string.",
1772
0
     function );
1773
1774
0
    return( -1 );
1775
0
  }
1776
0
  return( 1 );
1777
0
}
1778
1779
/* Retrieves the size of the UTF-8 encoded last mount path
1780
 * The returned size includes the end of string character
1781
 * Returns 1 if successful, 0 if not available or -1 on error
1782
 */
1783
int libfsext_superblock_get_utf8_last_mount_path_size(
1784
     libfsext_superblock_t *superblock,
1785
     size_t *utf8_string_size,
1786
     libcerror_error_t **error )
1787
258
{
1788
258
  static char *function = "libfsext_superblock_get_utf8_last_mount_path_size";
1789
1790
258
  if( superblock == NULL )
1791
0
  {
1792
0
    libcerror_error_set(
1793
0
     error,
1794
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1795
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1796
0
     "%s: invalid superblock.",
1797
0
     function );
1798
1799
0
    return( -1 );
1800
0
  }
1801
258
  if( libuna_utf8_string_size_from_utf8_stream(
1802
258
       superblock->last_mount_path,
1803
258
       64,
1804
258
       utf8_string_size,
1805
258
       error ) != 1 )
1806
191
  {
1807
191
    libcerror_error_set(
1808
191
     error,
1809
191
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1810
191
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1811
191
     "%s: unable to retrieve UTF-8 string size.",
1812
191
     function );
1813
1814
191
    return( -1 );
1815
191
  }
1816
67
  return( 1 );
1817
258
}
1818
1819
/* Retrieves the UTF-8 encoded last mount path
1820
 * The size should include the end of string character
1821
 * Returns 1 if successful, 0 if not available or -1 on error
1822
 */
1823
int libfsext_superblock_get_utf8_last_mount_path(
1824
     libfsext_superblock_t *superblock,
1825
     uint8_t *utf8_string,
1826
     size_t utf8_string_size,
1827
     libcerror_error_t **error )
1828
258
{
1829
258
  static char *function = "libfsext_superblock_get_utf8_last_mount_path";
1830
1831
258
  if( superblock == NULL )
1832
0
  {
1833
0
    libcerror_error_set(
1834
0
     error,
1835
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1836
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1837
0
     "%s: invalid superblock.",
1838
0
     function );
1839
1840
0
    return( -1 );
1841
0
  }
1842
258
  if( libuna_utf8_string_copy_from_utf8_stream(
1843
258
       utf8_string,
1844
258
       utf8_string_size,
1845
258
       superblock->last_mount_path,
1846
258
       64,
1847
258
       error ) != 1 )
1848
202
  {
1849
202
    libcerror_error_set(
1850
202
     error,
1851
202
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1852
202
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1853
202
     "%s: unable to retrieve UTF-8 string.",
1854
202
     function );
1855
1856
202
    return( -1 );
1857
202
  }
1858
56
  return( 1 );
1859
258
}
1860
1861
/* Retrieves the size of the UTF-16 encoded last mount path
1862
 * The returned size includes the end of string character
1863
 * Returns 1 if successful, 0 if not available or -1 on error
1864
 */
1865
int libfsext_superblock_get_utf16_last_mount_path_size(
1866
     libfsext_superblock_t *superblock,
1867
     size_t *utf16_string_size,
1868
     libcerror_error_t **error )
1869
0
{
1870
0
  static char *function = "libfsext_superblock_get_utf16_last_mount_path_size";
1871
1872
0
  if( superblock == NULL )
1873
0
  {
1874
0
    libcerror_error_set(
1875
0
     error,
1876
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1877
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1878
0
     "%s: invalid superblock.",
1879
0
     function );
1880
1881
0
    return( -1 );
1882
0
  }
1883
0
  if( libuna_utf16_string_size_from_utf8_stream(
1884
0
       superblock->last_mount_path,
1885
0
       64,
1886
0
       utf16_string_size,
1887
0
       error ) != 1 )
1888
0
  {
1889
0
    libcerror_error_set(
1890
0
     error,
1891
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1892
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1893
0
     "%s: unable to retrieve UTF-16 string size.",
1894
0
     function );
1895
1896
0
    return( -1 );
1897
0
  }
1898
0
  return( 1 );
1899
0
}
1900
1901
/* Retrieves the UTF-16 encoded last mount path
1902
 * The size should include the end of string character
1903
 * Returns 1 if successful, 0 if not available or -1 on error
1904
 */
1905
int libfsext_superblock_get_utf16_last_mount_path(
1906
     libfsext_superblock_t *superblock,
1907
     uint16_t *utf16_string,
1908
     size_t utf16_string_size,
1909
     libcerror_error_t **error )
1910
0
{
1911
0
  static char *function = "libfsext_superblock_get_utf16_last_mount_path";
1912
1913
0
  if( superblock == NULL )
1914
0
  {
1915
0
    libcerror_error_set(
1916
0
     error,
1917
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1918
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1919
0
     "%s: invalid superblock.",
1920
0
     function );
1921
1922
0
    return( -1 );
1923
0
  }
1924
0
  if( libuna_utf16_string_copy_from_utf8_stream(
1925
0
       utf16_string,
1926
0
       utf16_string_size,
1927
0
       superblock->last_mount_path,
1928
0
       64,
1929
0
       error ) != 1 )
1930
0
  {
1931
0
    libcerror_error_set(
1932
0
     error,
1933
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1934
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1935
0
     "%s: unable to retrieve UTF-16 string.",
1936
0
     function );
1937
1938
0
    return( -1 );
1939
0
  }
1940
0
  return( 1 );
1941
0
}
1942