Coverage Report

Created: 2025-07-04 07:01

/src/libfsext/libfsext/libfsext_group_descriptor.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Group descriptor 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 "libfsext_checksum.h"
28
#include "libfsext_definitions.h"
29
#include "libfsext_group_descriptor.h"
30
#include "libfsext_io_handle.h"
31
#include "libfsext_libbfio.h"
32
#include "libfsext_libcerror.h"
33
#include "libfsext_libcnotify.h"
34
35
#include "fsext_group_descriptor.h"
36
37
/* Creates a group descriptor
38
 * Make sure the value group_descriptor is referencing, is set to NULL
39
 * Returns 1 if successful or -1 on error
40
 */
41
int libfsext_group_descriptor_initialize(
42
     libfsext_group_descriptor_t **group_descriptor,
43
     libcerror_error_t **error )
44
4.88M
{
45
4.88M
  static char *function = "libfsext_group_descriptor_initialize";
46
47
4.88M
  if( group_descriptor == 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 group descriptor.",
54
0
     function );
55
56
0
    return( -1 );
57
0
  }
58
4.88M
  if( *group_descriptor != 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 group descriptor value already set.",
65
0
     function );
66
67
0
    return( -1 );
68
0
  }
69
4.88M
  *group_descriptor = memory_allocate_structure(
70
4.88M
                       libfsext_group_descriptor_t );
71
72
4.88M
  if( *group_descriptor == 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 group descriptor.",
79
0
     function );
80
81
0
    goto on_error;
82
0
  }
83
4.88M
  if( memory_set(
84
4.88M
       *group_descriptor,
85
4.88M
       0,
86
4.88M
       sizeof( libfsext_group_descriptor_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 group descriptor.",
93
0
     function );
94
95
0
    goto on_error;
96
0
  }
97
4.88M
  return( 1 );
98
99
0
on_error:
100
0
  if( *group_descriptor != NULL )
101
0
  {
102
0
    memory_free(
103
0
     *group_descriptor );
104
105
0
    *group_descriptor = NULL;
106
0
  }
107
0
  return( -1 );
108
4.88M
}
109
110
/* Frees a group descriptor
111
 * Returns 1 if successful or -1 on error
112
 */
113
int libfsext_group_descriptor_free(
114
     libfsext_group_descriptor_t **group_descriptor,
115
     libcerror_error_t **error )
116
4.88M
{
117
4.88M
  static char *function = "libfsext_group_descriptor_free";
118
119
4.88M
  if( group_descriptor == 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 group descriptor.",
126
0
     function );
127
128
0
    return( -1 );
129
0
  }
130
4.88M
  if( *group_descriptor != NULL )
131
4.88M
  {
132
4.88M
    memory_free(
133
4.88M
     *group_descriptor );
134
135
4.88M
    *group_descriptor = NULL;
136
4.88M
  }
137
4.88M
  return( 1 );
138
4.88M
}
139
140
/* Reads the group descriptor data
141
 * Returns 1 if successful or -1 on error
142
 */
143
int libfsext_group_descriptor_read_data(
144
     libfsext_group_descriptor_t *group_descriptor,
145
     libfsext_io_handle_t *io_handle,
146
     const uint8_t *data,
147
     size_t data_size,
148
     libcerror_error_t **error )
149
4.88M
{
150
4.88M
  uint8_t checksum_data[ 4 ];
151
4.88M
  uint8_t empty_checksum_data[ 2 ]  = { 0, 0 };
152
153
4.88M
  static char *function             = "libfsext_group_descriptor_read_data";
154
4.88M
  size_t group_descriptor_data_size = 0;
155
4.88M
  uint64_t value_64bit              = 0;
156
4.88M
  uint32_t calculated_checksum      = 0;
157
4.88M
  uint32_t stored_checksum          = 0;
158
4.88M
  uint32_t value_32bit              = 0;
159
4.88M
  uint16_t value_16bit              = 0;
160
161
4.88M
  if( group_descriptor == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid group descriptor.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
4.88M
  if( io_handle == NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
178
0
     "%s: invalid IO handle.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
4.88M
  if( io_handle->format_version < 4 )
184
716k
  {
185
716k
    group_descriptor_data_size = sizeof( fsext_group_descriptor_ext2_t );
186
716k
  }
187
4.17M
  else if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 )
188
4.17M
        && ( io_handle->group_descriptor_size > 32 ) )
189
53.6k
  {
190
53.6k
    group_descriptor_data_size = 64;
191
53.6k
  }
192
4.11M
  else
193
4.11M
  {
194
4.11M
    group_descriptor_data_size = 32;
195
4.11M
  }
196
4.88M
  if( data == NULL )
197
0
  {
198
0
    libcerror_error_set(
199
0
     error,
200
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
201
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
202
0
     "%s: invalid data.",
203
0
     function );
204
205
0
    return( -1 );
206
0
  }
207
4.88M
  if( data_size < group_descriptor_data_size )
208
0
  {
209
0
    libcerror_error_set(
210
0
     error,
211
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
212
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
213
0
     "%s: invalid data size value too small.",
214
0
     function );
215
216
0
    return( -1 );
217
0
  }
218
4.88M
  if( data_size > (size_t) SSIZE_MAX )
219
0
  {
220
0
    libcerror_error_set(
221
0
     error,
222
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
224
0
     "%s: invalid data size value exceeds maximum.",
225
0
     function );
226
227
0
    return( -1 );
228
0
  }
229
#if defined( HAVE_DEBUG_OUTPUT )
230
  if( libcnotify_verbose != 0 )
231
  {
232
    libcnotify_printf(
233
     "%s: group descriptor data:\n",
234
     function );
235
    libcnotify_print_data(
236
     data,
237
     group_descriptor_data_size,
238
     0 );
239
  }
240
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
241
242
4.88M
  byte_stream_copy_to_uint32_little_endian(
243
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->block_bitmap_block_number,
244
4.88M
   group_descriptor->block_bitmap_block_number );
245
246
4.88M
  byte_stream_copy_to_uint32_little_endian(
247
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->inode_bitmap_block_number,
248
4.88M
   group_descriptor->inode_bitmap_block_number );
249
250
4.88M
  byte_stream_copy_to_uint32_little_endian(
251
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->inode_table_block_number,
252
4.88M
   group_descriptor->inode_table_block_number );
253
254
4.88M
  byte_stream_copy_to_uint16_little_endian(
255
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->number_of_unallocated_blocks,
256
4.88M
   group_descriptor->number_of_unallocated_blocks );
257
258
4.88M
  byte_stream_copy_to_uint16_little_endian(
259
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->number_of_unallocated_inodes,
260
4.88M
   group_descriptor->number_of_unallocated_inodes );
261
262
4.88M
  byte_stream_copy_to_uint16_little_endian(
263
4.88M
   ( (fsext_group_descriptor_ext2_t *) data )->number_of_directories,
264
4.88M
   group_descriptor->number_of_directories );
265
266
4.88M
  if( io_handle->format_version < 4 )
267
716k
  {
268
#if defined( HAVE_DEBUG_OUTPUT )
269
    if( libcnotify_verbose != 0 )
270
    {
271
      libcnotify_printf(
272
       "%s: block bitmap block number\t\t: %" PRIu64 "\n",
273
       function,
274
       group_descriptor->block_bitmap_block_number );
275
276
      libcnotify_printf(
277
       "%s: inode bitmap block number\t\t: %" PRIu64 "\n",
278
       function,
279
       group_descriptor->inode_bitmap_block_number );
280
281
      libcnotify_printf(
282
       "%s: inode table block number\t\t: %" PRIu64 "\n",
283
       function,
284
       group_descriptor->inode_table_block_number );
285
286
      libcnotify_printf(
287
       "%s: number of unallocated blocks\t: %" PRIu32 "\n",
288
       function,
289
       group_descriptor->number_of_unallocated_blocks );
290
291
      libcnotify_printf(
292
       "%s: number of unallocated inodes\t: %" PRIu32 "\n",
293
       function,
294
       group_descriptor->number_of_unallocated_inodes );
295
296
      libcnotify_printf(
297
       "%s: number of directories\t\t: %" PRIu32 "\n",
298
       function,
299
       group_descriptor->number_of_directories );
300
301
      libcnotify_printf(
302
       "%s: padding1:\n",
303
       function );
304
      libcnotify_print_data(
305
       ( (fsext_group_descriptor_ext2_t *) data )->padding1,
306
       2,
307
       0 );
308
309
      libcnotify_printf(
310
       "%s: unknown1:\n",
311
       function );
312
      libcnotify_print_data(
313
       ( (fsext_group_descriptor_ext2_t *) data )->unknown1,
314
       12,
315
       0 );
316
    }
317
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
318
716k
  }
319
4.17M
  else
320
4.17M
  {
321
4.17M
    byte_stream_copy_to_uint32_little_endian(
322
4.17M
     ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_lower,
323
4.17M
     group_descriptor->exclude_bitmap_block_number );
324
325
4.17M
    byte_stream_copy_to_uint16_little_endian(
326
4.17M
     ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_lower,
327
4.17M
     group_descriptor->block_bitmap_checksum );
328
329
4.17M
    byte_stream_copy_to_uint16_little_endian(
330
4.17M
     ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_lower,
331
4.17M
     group_descriptor->inode_bitmap_checksum );
332
333
4.17M
    byte_stream_copy_to_uint16_little_endian(
334
4.17M
     ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_lower,
335
4.17M
     group_descriptor->number_of_unused_inodes );
336
337
4.17M
    byte_stream_copy_to_uint16_little_endian(
338
4.17M
     ( (fsext_group_descriptor_ext4_t *) data )->checksum,
339
4.17M
     value_16bit );
340
341
4.17M
    stored_checksum = value_16bit;
342
343
#if defined( HAVE_DEBUG_OUTPUT )
344
    if( libcnotify_verbose != 0 )
345
    {
346
      libcnotify_printf(
347
       "%s: block bitmap block number (lower)\t\t: %" PRIu64 "\n",
348
       function,
349
       group_descriptor->block_bitmap_block_number );
350
351
      libcnotify_printf(
352
       "%s: inode bitmap block number (lower)\t\t: %" PRIu64 "\n",
353
       function,
354
       group_descriptor->inode_bitmap_block_number );
355
356
      libcnotify_printf(
357
       "%s: inode table block number (lower)\t\t: %" PRIu64 "\n",
358
       function,
359
       group_descriptor->inode_table_block_number );
360
361
      libcnotify_printf(
362
       "%s: number of unallocated blocks (lower)\t: %" PRIu32 "\n",
363
       function,
364
       group_descriptor->number_of_unallocated_blocks );
365
366
      libcnotify_printf(
367
       "%s: number of unallocated inodes (lower)\t: %" PRIu32 "\n",
368
       function,
369
       group_descriptor->number_of_unallocated_inodes );
370
371
      libcnotify_printf(
372
       "%s: number of directories (lower)\t\t: %" PRIu32 "\n",
373
       function,
374
       group_descriptor->number_of_directories );
375
376
      libcnotify_printf(
377
       "%s: exclude bitmap block number (lower)\t: %" PRIu64 "\n",
378
       function,
379
       group_descriptor->exclude_bitmap_block_number );
380
381
      libcnotify_printf(
382
       "%s: block bitmap checksum (lower)\t\t: 0x%04" PRIx32 "\n",
383
       function,
384
       group_descriptor->block_bitmap_checksum );
385
386
      libcnotify_printf(
387
       "%s: inode bitmap checksum (lower)\t\t: 0x%04" PRIx32 "\n",
388
       function,
389
       group_descriptor->inode_bitmap_checksum );
390
391
      libcnotify_printf(
392
       "%s: number of unused inodes (lower)\t\t: %" PRIu32 "\n",
393
       function,
394
       group_descriptor->number_of_unused_inodes );
395
396
      byte_stream_copy_to_uint16_little_endian(
397
       ( (fsext_group_descriptor_ext4_t *) data )->checksum,
398
       value_16bit );
399
      libcnotify_printf(
400
       "%s: checksum\t\t\t\t\t: 0x%04" PRIx16 "\n",
401
       function,
402
       value_16bit );
403
    }
404
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
405
4.17M
    if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 )
406
4.17M
     && ( io_handle->group_descriptor_size > 32 ) )
407
53.6k
    {
408
#if defined( HAVE_DEBUG_OUTPUT )
409
      if( libcnotify_verbose != 0 )
410
      {
411
        byte_stream_copy_to_uint32_little_endian(
412
         ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_block_number_upper,
413
         value_32bit );
414
        libcnotify_printf(
415
         "%s: block bitmap block number (upper)\t\t: %" PRIu32 "\n",
416
         function,
417
         value_32bit );
418
419
        byte_stream_copy_to_uint32_little_endian(
420
         ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_block_number_upper,
421
         value_32bit );
422
        libcnotify_printf(
423
         "%s: inode bitmap block number (upper)\t\t: %" PRIu32 "\n",
424
         function,
425
         value_32bit );
426
427
        byte_stream_copy_to_uint32_little_endian(
428
         ( (fsext_group_descriptor_ext4_t *) data )->inode_table_block_number_upper,
429
         value_32bit );
430
        libcnotify_printf(
431
         "%s: inode table block number (upper)\t\t: %" PRIu32 "\n",
432
         function,
433
         value_32bit );
434
435
        byte_stream_copy_to_uint16_little_endian(
436
         ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_blocks_upper,
437
         value_16bit );
438
        libcnotify_printf(
439
         "%s: number of unallocated blocks (upper)\t: %" PRIu16 "\n",
440
         function,
441
         value_16bit );
442
443
        byte_stream_copy_to_uint16_little_endian(
444
         ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_inodes_upper,
445
         value_16bit );
446
        libcnotify_printf(
447
         "%s: number of unallocated inodes (upper)\t: %" PRIu16 "\n",
448
         function,
449
         value_16bit );
450
451
        byte_stream_copy_to_uint16_little_endian(
452
         ( (fsext_group_descriptor_ext4_t *) data )->number_of_directories_upper,
453
         value_16bit );
454
        libcnotify_printf(
455
         "%s: number of directories (upper)\t\t: %" PRIu16 "\n",
456
         function,
457
         value_16bit );
458
459
        byte_stream_copy_to_uint16_little_endian(
460
         ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_upper,
461
         value_16bit );
462
        libcnotify_printf(
463
         "%s: number of unused inodes (upper)\t\t: %" PRIu16 "\n",
464
         function,
465
         value_16bit );
466
467
        byte_stream_copy_to_uint32_little_endian(
468
         ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_upper,
469
         value_32bit );
470
        libcnotify_printf(
471
         "%s: exclude bitmap block number (upper)\t: %" PRIu32 "\n",
472
         function,
473
         value_32bit );
474
475
        byte_stream_copy_to_uint16_little_endian(
476
         ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_upper,
477
         value_16bit );
478
        libcnotify_printf(
479
         "%s: block bitmap checksum (upper)\t\t: 0x%04" PRIx16 "\n",
480
         function,
481
         value_16bit );
482
483
        byte_stream_copy_to_uint16_little_endian(
484
         ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_upper,
485
         value_16bit );
486
        libcnotify_printf(
487
         "%s: inode bitmap checksum (upper)\t\t: 0x%04" PRIx16 "\n",
488
         function,
489
         value_16bit );
490
491
        libcnotify_printf(
492
         "%s: unknown1:\n",
493
         function );
494
        libcnotify_print_data(
495
         ( (fsext_group_descriptor_ext4_t *) data )->unknown1,
496
         4,
497
         0 );
498
      }
499
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
500
501
53.6k
      byte_stream_copy_to_uint32_little_endian(
502
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_block_number_upper,
503
53.6k
       value_64bit );
504
505
53.6k
      group_descriptor->block_bitmap_block_number |= value_64bit << 32;
506
507
53.6k
      byte_stream_copy_to_uint32_little_endian(
508
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_block_number_upper,
509
53.6k
       value_64bit );
510
511
53.6k
      group_descriptor->inode_bitmap_block_number |= value_64bit << 32;
512
513
53.6k
      byte_stream_copy_to_uint32_little_endian(
514
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->inode_table_block_number_upper,
515
53.6k
       value_64bit );
516
517
53.6k
      group_descriptor->inode_table_block_number |= value_64bit << 32;
518
519
53.6k
      byte_stream_copy_to_uint16_little_endian(
520
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_blocks_upper,
521
53.6k
       value_32bit );
522
523
53.6k
      group_descriptor->number_of_unallocated_blocks |= value_32bit << 16;
524
525
53.6k
      byte_stream_copy_to_uint16_little_endian(
526
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->number_of_unallocated_inodes_upper,
527
53.6k
       value_32bit );
528
529
53.6k
      group_descriptor->number_of_unallocated_inodes |= value_32bit << 16;
530
531
53.6k
      byte_stream_copy_to_uint16_little_endian(
532
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->number_of_directories_upper,
533
53.6k
       value_32bit );
534
535
53.6k
      group_descriptor->number_of_directories |= value_32bit << 16;
536
537
53.6k
      byte_stream_copy_to_uint16_little_endian(
538
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->number_of_unused_inodes_upper,
539
53.6k
       value_32bit );
540
541
53.6k
      group_descriptor->number_of_unused_inodes |= value_32bit << 16;
542
543
53.6k
      byte_stream_copy_to_uint32_little_endian(
544
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->exclude_bitmap_block_number_upper,
545
53.6k
       value_64bit );
546
547
53.6k
      group_descriptor->exclude_bitmap_block_number |= value_64bit << 32;
548
549
53.6k
      byte_stream_copy_to_uint16_little_endian(
550
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->block_bitmap_checksum_upper,
551
53.6k
       value_32bit );
552
553
53.6k
      group_descriptor->block_bitmap_checksum |= value_32bit << 16;
554
555
53.6k
      byte_stream_copy_to_uint16_little_endian(
556
53.6k
       ( (fsext_group_descriptor_ext4_t *) data )->inode_bitmap_checksum_upper,
557
53.6k
       value_32bit );
558
559
53.6k
      group_descriptor->inode_bitmap_checksum |= value_32bit << 16;
560
53.6k
    }
561
#if defined( HAVE_DEBUG_OUTPUT )
562
    if( libcnotify_verbose != 0 )
563
    {
564
      libcnotify_printf(
565
       "%s: block bitmap block number\t\t\t: %" PRIu64 "\n",
566
       function,
567
       group_descriptor->block_bitmap_block_number );
568
569
      libcnotify_printf(
570
       "%s: inode bitmap block number\t\t\t: %" PRIu64 "\n",
571
       function,
572
       group_descriptor->inode_bitmap_block_number );
573
574
      libcnotify_printf(
575
       "%s: inode table block number\t\t\t: %" PRIu64 "\n",
576
       function,
577
       group_descriptor->inode_table_block_number );
578
579
      libcnotify_printf(
580
       "%s: number of unallocated blocks\t\t: %" PRIu32 "\n",
581
       function,
582
       group_descriptor->number_of_unallocated_blocks );
583
584
      libcnotify_printf(
585
       "%s: number of unallocated inodes\t\t: %" PRIu32 "\n",
586
       function,
587
       group_descriptor->number_of_unallocated_inodes );
588
589
      libcnotify_printf(
590
       "%s: number of directories\t\t\t: %" PRIu32 "\n",
591
       function,
592
       group_descriptor->number_of_directories );
593
594
      libcnotify_printf(
595
       "%s: number of unused inodes\t\t\t: %" PRIu32 "\n",
596
       function,
597
       group_descriptor->number_of_unused_inodes );
598
599
      if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 )
600
      {
601
        libcnotify_printf(
602
         "%s: block bitmap checksum\t\t\t: 0x%08" PRIx32 "\n",
603
         function,
604
         group_descriptor->block_bitmap_checksum );
605
606
        libcnotify_printf(
607
         "%s: inode bitmap checksum\t\t\t: 0x%08" PRIx32 "\n",
608
         function,
609
         group_descriptor->inode_bitmap_checksum );
610
      }
611
      else
612
      {
613
        libcnotify_printf(
614
         "%s: block bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
615
         function,
616
         group_descriptor->block_bitmap_checksum );
617
618
        libcnotify_printf(
619
         "%s: inode bitmap checksum\t\t\t: 0x%04" PRIx32 "\n",
620
         function,
621
         group_descriptor->inode_bitmap_checksum );
622
      }
623
      libcnotify_printf(
624
       "\n" );
625
    }
626
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
627
4.17M
  }
628
/* TODO add support for crc16 checksum */
629
4.88M
  if( ( io_handle->read_only_compatible_features_flags & LIBFSEXT_READ_ONLY_COMPATIBLE_FEATURES_FLAG_METADATA_CHECKSUM ) != 0 )
630
261k
  {
631
261k
    byte_stream_copy_from_uint32_little_endian(
632
261k
     checksum_data,
633
261k
     group_descriptor->group_number );
634
635
261k
    if( libfsext_checksum_calculate_crc32(
636
261k
         &calculated_checksum,
637
261k
         checksum_data,
638
261k
         4,
639
261k
         io_handle->metadata_checksum_seed,
640
261k
         error ) != 1 )
641
0
    {
642
0
      libcerror_error_set(
643
0
       error,
644
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
645
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
646
0
       "%s: unable to calculate CRC-32.",
647
0
       function );
648
649
0
      return( -1 );
650
0
    }
651
261k
    if( libfsext_checksum_calculate_crc32(
652
261k
         &calculated_checksum,
653
261k
         data,
654
261k
         30,
655
261k
         calculated_checksum,
656
261k
         error ) != 1 )
657
0
    {
658
0
      libcerror_error_set(
659
0
       error,
660
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
661
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
662
0
       "%s: unable to calculate CRC-32.",
663
0
       function );
664
665
0
      return( -1 );
666
0
    }
667
261k
    if( libfsext_checksum_calculate_crc32(
668
261k
         &calculated_checksum,
669
261k
         empty_checksum_data,
670
261k
         2,
671
261k
         calculated_checksum,
672
261k
         error ) != 1 )
673
0
    {
674
0
      libcerror_error_set(
675
0
       error,
676
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
677
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
678
0
       "%s: unable to calculate CRC-32.",
679
0
       function );
680
681
0
      return( -1 );
682
0
    }
683
261k
    if( libfsext_checksum_calculate_crc32(
684
261k
         &calculated_checksum,
685
261k
         &( data[ 32 ] ),
686
261k
         data_size - 32,
687
261k
         calculated_checksum,
688
261k
         error ) != 1 )
689
0
    {
690
0
      libcerror_error_set(
691
0
       error,
692
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
693
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
694
0
       "%s: unable to calculate CRC-32.",
695
0
       function );
696
697
0
      return( -1 );
698
0
    }
699
261k
    calculated_checksum = ( 0xffffffffUL - calculated_checksum ) & 0x0000ffffUL;
700
701
261k
    if( ( stored_checksum != 0 )
702
261k
     && ( stored_checksum != calculated_checksum ) )
703
131k
    {
704
#if defined( HAVE_DEBUG_OUTPUT )
705
      if( libcnotify_verbose != 0 )
706
      {
707
        libcnotify_printf(
708
         "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).\n",
709
         function,
710
         stored_checksum,
711
         calculated_checksum );
712
      }
713
#endif
714
131k
    }
715
261k
  }
716
4.88M
  return( 1 );
717
4.88M
}
718
719
/* Reads the group descriptor from a Basic File IO (bfio) handle
720
 * Returns 1 if successful or -1 on error
721
 */
722
int libfsext_group_descriptor_read_file_io_handle(
723
     libfsext_group_descriptor_t *group_descriptor,
724
     libfsext_io_handle_t *io_handle,
725
     libbfio_handle_t *file_io_handle,
726
     libcerror_error_t **error )
727
4.88M
{
728
4.88M
  uint8_t *data                     = NULL;
729
4.88M
  static char *function             = "libfsext_group_descriptor_read_file_io_handle";
730
4.88M
  size_t group_descriptor_data_size = 0;
731
4.88M
  ssize_t read_count                = 0;
732
733
4.88M
  if( io_handle == NULL )
734
0
  {
735
0
    libcerror_error_set(
736
0
     error,
737
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
738
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
739
0
     "%s: invalid IO handle.",
740
0
     function );
741
742
0
    return( -1 );
743
0
  }
744
4.88M
  if( io_handle == NULL )
745
0
  {
746
0
    libcerror_error_set(
747
0
     error,
748
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
749
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
750
0
     "%s: invalid IO handle.",
751
0
     function );
752
753
0
    return( -1 );
754
0
  }
755
4.88M
  if( io_handle->format_version < 4 )
756
716k
  {
757
716k
    group_descriptor_data_size = sizeof( fsext_group_descriptor_ext2_t );
758
716k
  }
759
4.17M
  else if( ( ( io_handle->incompatible_features_flags & LIBFSEXT_INCOMPATIBLE_FEATURES_FLAG_64BIT_SUPPORT ) != 0 )
760
4.17M
        && ( io_handle->group_descriptor_size > 32 ) )
761
53.7k
  {
762
53.7k
    group_descriptor_data_size = 64;
763
53.7k
  }
764
4.11M
  else
765
4.11M
  {
766
4.11M
    group_descriptor_data_size = 32;
767
4.11M
  }
768
4.88M
  data = (uint8_t *) memory_allocate(
769
4.88M
                      sizeof( uint8_t ) * group_descriptor_data_size );
770
771
4.88M
  if( data == NULL )
772
0
  {
773
0
    libcerror_error_set(
774
0
     error,
775
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
776
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
777
0
     "%s: unable to create data.",
778
0
     function );
779
780
0
    goto on_error;
781
0
  }
782
4.88M
  read_count = libbfio_handle_read_buffer(
783
4.88M
                file_io_handle,
784
4.88M
                data,
785
4.88M
                group_descriptor_data_size,
786
4.88M
                error );
787
788
4.88M
  if( read_count != (ssize_t) group_descriptor_data_size )
789
390
  {
790
390
    libcerror_error_set(
791
390
     error,
792
390
     LIBCERROR_ERROR_DOMAIN_IO,
793
390
     LIBCERROR_IO_ERROR_READ_FAILED,
794
390
     "%s: unable to read group descriptor.",
795
390
     function );
796
797
390
    goto on_error;
798
390
  }
799
4.88M
  if( libfsext_group_descriptor_read_data(
800
4.88M
       group_descriptor,
801
4.88M
       io_handle,
802
4.88M
       data,
803
4.88M
       group_descriptor_data_size,
804
4.88M
       error ) != 1 )
805
0
  {
806
0
    libcerror_error_set(
807
0
     error,
808
0
     LIBCERROR_ERROR_DOMAIN_IO,
809
0
     LIBCERROR_IO_ERROR_READ_FAILED,
810
0
     "%s: unable to read group descriptor.",
811
0
     function );
812
813
0
    goto on_error;
814
0
  }
815
4.88M
  memory_free(
816
4.88M
   data );
817
818
4.88M
  return( 1 );
819
820
390
on_error:
821
390
  if( data != NULL )
822
390
  {
823
390
    memory_free(
824
390
     data );
825
390
  }
826
390
  return( -1 );
827
4.88M
}
828