Coverage Report

Created: 2024-06-12 07:07

/src/libfsapfs/libfsapfs/libfsapfs_container_superblock.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The container superblock functions
3
 *
4
 * Copyright (C) 2018-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 "libfsapfs_checksum.h"
28
#include "libfsapfs_container_superblock.h"
29
#include "libfsapfs_debug.h"
30
#include "libfsapfs_io_handle.h"
31
#include "libfsapfs_libbfio.h"
32
#include "libfsapfs_libcerror.h"
33
#include "libfsapfs_libcnotify.h"
34
#include "libfsapfs_libfguid.h"
35
36
#include "fsapfs_container_superblock.h"
37
38
/* Creates a container superblock
39
 * Make sure the value container_superblock is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libfsapfs_container_superblock_initialize(
43
     libfsapfs_container_superblock_t **container_superblock,
44
     libcerror_error_t **error )
45
44.2k
{
46
44.2k
  static char *function = "libfsapfs_container_superblock_initialize";
47
48
44.2k
  if( container_superblock == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid container superblock.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
44.2k
  if( *container_superblock != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid container superblock value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
44.2k
  *container_superblock = memory_allocate_structure(
71
44.2k
                           libfsapfs_container_superblock_t );
72
73
44.2k
  if( *container_superblock == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create container superblock.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
44.2k
  if( memory_set(
85
44.2k
       *container_superblock,
86
44.2k
       0,
87
44.2k
       sizeof( libfsapfs_container_superblock_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear container superblock.",
94
0
     function );
95
96
0
    goto on_error;
97
0
  }
98
44.2k
  return( 1 );
99
100
0
on_error:
101
0
  if( *container_superblock != NULL )
102
0
  {
103
0
    memory_free(
104
0
     *container_superblock );
105
106
0
    *container_superblock = NULL;
107
0
  }
108
0
  return( -1 );
109
44.2k
}
110
111
/* Frees a container superblock
112
 * Returns 1 if successful or -1 on error
113
 */
114
int libfsapfs_container_superblock_free(
115
     libfsapfs_container_superblock_t **container_superblock,
116
     libcerror_error_t **error )
117
44.2k
{
118
44.2k
  static char *function = "libfsapfs_container_superblock_free";
119
120
44.2k
  if( container_superblock == NULL )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
126
0
     "%s: invalid container superblock.",
127
0
     function );
128
129
0
    return( -1 );
130
0
  }
131
44.2k
  if( *container_superblock != NULL )
132
44.2k
  {
133
44.2k
    memory_free(
134
44.2k
     *container_superblock );
135
136
44.2k
    *container_superblock = NULL;
137
44.2k
  }
138
44.2k
  return( 1 );
139
44.2k
}
140
141
/* Reads the container superblock
142
 * Returns 1 if successful or -1 on error
143
 */
144
int libfsapfs_container_superblock_read_file_io_handle(
145
     libfsapfs_container_superblock_t *container_superblock,
146
     libbfio_handle_t *file_io_handle,
147
     off64_t file_offset,
148
     libcerror_error_t **error )
149
44.2k
{
150
44.2k
  uint8_t container_superblock_data[ 4096 ];
151
152
44.2k
  static char *function = "libfsapfs_container_superblock_read_file_io_handle";
153
44.2k
  ssize_t read_count    = 0;
154
155
44.2k
  if( container_superblock == NULL )
156
0
  {
157
0
    libcerror_error_set(
158
0
     error,
159
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
160
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
161
0
     "%s: invalid container superblock.",
162
0
     function );
163
164
0
    return( -1 );
165
0
  }
166
#if defined( HAVE_DEBUG_OUTPUT )
167
  if( libcnotify_verbose != 0 )
168
  {
169
    libcnotify_printf(
170
     "%s: reading container superblock at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
171
     function,
172
     file_offset,
173
     file_offset );
174
  }
175
#endif
176
44.2k
  read_count = libbfio_handle_read_buffer_at_offset(
177
44.2k
                file_io_handle,
178
44.2k
                (uint8_t *) &container_superblock_data,
179
44.2k
                4096,
180
44.2k
                file_offset,
181
44.2k
                error );
182
183
44.2k
  if( read_count != (ssize_t) 4096 )
184
121
  {
185
121
    libcerror_error_set(
186
121
     error,
187
121
     LIBCERROR_ERROR_DOMAIN_IO,
188
121
     LIBCERROR_IO_ERROR_READ_FAILED,
189
121
     "%s: unable to read container superblock data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
190
121
     function,
191
121
     file_offset,
192
121
     file_offset );
193
194
121
    return( -1 );
195
121
  }
196
44.1k
  if( libfsapfs_container_superblock_read_data(
197
44.1k
       container_superblock,
198
44.1k
       (uint8_t *) &container_superblock_data,
199
44.1k
       4096,
200
44.1k
       error ) != 1 )
201
1.20k
  {
202
1.20k
    libcerror_error_set(
203
1.20k
     error,
204
1.20k
     LIBCERROR_ERROR_DOMAIN_IO,
205
1.20k
     LIBCERROR_IO_ERROR_READ_FAILED,
206
1.20k
     "%s: unable to read container superblock data.",
207
1.20k
     function );
208
209
1.20k
    return( -1 );
210
1.20k
  }
211
42.9k
  return( 1 );
212
44.1k
}
213
214
/* Reads the container superblock
215
 * Returns 1 if successful or -1 on error
216
 */
217
int libfsapfs_container_superblock_read_data(
218
     libfsapfs_container_superblock_t *container_superblock,
219
     const uint8_t *data,
220
     size_t data_size,
221
     libcerror_error_t **error )
222
44.1k
{
223
44.1k
  static char *function              = "libfsapfs_container_superblock_read_data";
224
44.1k
  size_t data_offset                 = 0;
225
44.1k
  uint64_t calculated_checksum       = 0;
226
44.1k
  uint64_t stored_checksum           = 0;
227
44.1k
  uint64_t volume_object_identifier  = 0;
228
44.1k
  uint32_t maximum_number_of_volumes = 0;
229
44.1k
  uint32_t object_subtype            = 0;
230
44.1k
  uint32_t object_type               = 0;
231
44.1k
  int object_identifier_index        = 0;
232
233
#if defined( HAVE_DEBUG_OUTPUT )
234
  uint64_t value_64bit               = 0;
235
  uint32_t value_32bit               = 0;
236
  int counter_index                  = 0;
237
#endif
238
239
44.1k
  if( container_superblock == NULL )
240
0
  {
241
0
    libcerror_error_set(
242
0
     error,
243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
244
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
245
0
     "%s: invalid container superblock.",
246
0
     function );
247
248
0
    return( -1 );
249
0
  }
250
44.1k
  if( data == NULL )
251
0
  {
252
0
    libcerror_error_set(
253
0
     error,
254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
255
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
256
0
     "%s: invalid data.",
257
0
     function );
258
259
0
    return( -1 );
260
0
  }
261
44.1k
  if( ( data_size < sizeof( fsapfs_container_superblock_t ) )
262
44.1k
   || ( data_size > (size_t) SSIZE_MAX ) )
263
0
  {
264
0
    libcerror_error_set(
265
0
     error,
266
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
267
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
268
0
     "%s: invalid data size value out of bounds.",
269
0
     function );
270
271
0
    return( -1 );
272
0
  }
273
#if defined( HAVE_DEBUG_OUTPUT )
274
  if( libcnotify_verbose != 0 )
275
  {
276
    libcnotify_printf(
277
     "%s: container superblock data:\n",
278
     function );
279
    libcnotify_print_data(
280
     data,
281
     sizeof( fsapfs_container_superblock_t ),
282
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
283
  }
284
#endif
285
44.1k
  byte_stream_copy_to_uint64_little_endian(
286
44.1k
   ( (fsapfs_container_superblock_t *) data )->object_checksum,
287
44.1k
   stored_checksum );
288
289
44.1k
  byte_stream_copy_to_uint64_little_endian(
290
44.1k
   ( (fsapfs_container_superblock_t *) data )->object_transaction_identifier,
291
44.1k
   container_superblock->object_transaction_identifier );
292
293
44.1k
  byte_stream_copy_to_uint32_little_endian(
294
44.1k
   ( (fsapfs_container_superblock_t *) data )->object_type,
295
44.1k
   object_type );
296
297
44.1k
  if( object_type != 0x80000001UL )
298
165
  {
299
165
    libcerror_error_set(
300
165
     error,
301
165
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
302
165
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
303
165
     "%s: invalid object type: 0x%08" PRIx32 ".",
304
165
     function,
305
165
     object_type );
306
307
165
    return( -1 );
308
165
  }
309
43.9k
  byte_stream_copy_to_uint32_little_endian(
310
43.9k
   ( (fsapfs_container_superblock_t *) data )->object_subtype,
311
43.9k
   object_subtype );
312
313
43.9k
  if( object_subtype != 0x00000000UL )
314
107
  {
315
107
    libcerror_error_set(
316
107
     error,
317
107
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
318
107
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
319
107
     "%s: invalid object subtype: 0x%08" PRIx32 ".",
320
107
     function,
321
107
     object_subtype );
322
323
107
    return( -1 );
324
107
  }
325
43.8k
  if( memory_compare(
326
43.8k
       ( (fsapfs_container_superblock_t *) data )->signature,
327
43.8k
       fsapfs_container_signature,
328
43.8k
       4 ) != 0 )
329
128
  {
330
128
    libcerror_error_set(
331
128
     error,
332
128
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
128
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
334
128
     "%s: invalid signature.",
335
128
     function );
336
337
128
    return( -1 );
338
128
  }
339
43.7k
  byte_stream_copy_to_uint32_little_endian(
340
43.7k
   ( (fsapfs_container_superblock_t *) data )->block_size,
341
43.7k
   container_superblock->block_size );
342
343
43.7k
  byte_stream_copy_to_uint64_little_endian(
344
43.7k
   ( (fsapfs_container_superblock_t *) data )->number_of_blocks,
345
43.7k
   container_superblock->number_of_blocks );
346
347
43.7k
  byte_stream_copy_to_uint64_little_endian(
348
43.7k
   ( (fsapfs_container_superblock_t *) data )->incompatible_features_flags,
349
43.7k
   container_superblock->incompatible_features_flags );
350
351
43.7k
  if( memory_copy(
352
43.7k
       container_superblock->container_identifier,
353
43.7k
       ( (fsapfs_container_superblock_t *) data )->container_identifier,
354
43.7k
       16 ) == NULL )
355
0
  {
356
0
    libcerror_error_set(
357
0
     error,
358
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
359
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
360
0
     "%s: unable to copy container identifier.",
361
0
     function );
362
363
0
    return( -1 );
364
0
  }
365
43.7k
  byte_stream_copy_to_uint64_little_endian(
366
43.7k
   ( (fsapfs_container_superblock_t *) data )->space_manager_object_identifier,
367
43.7k
   container_superblock->space_manager_object_identifier );
368
369
43.7k
  byte_stream_copy_to_uint64_little_endian(
370
43.7k
   ( (fsapfs_container_superblock_t *) data )->object_map_block_number,
371
43.7k
   container_superblock->object_map_block_number );
372
373
43.7k
  byte_stream_copy_to_uint64_little_endian(
374
43.7k
   ( (fsapfs_container_superblock_t *) data )->reaper_object_identifier,
375
43.7k
   container_superblock->reaper_object_identifier );
376
377
43.7k
  byte_stream_copy_to_uint32_little_endian(
378
43.7k
   ( (fsapfs_container_superblock_t *) data )->maximum_number_of_volumes,
379
43.7k
   maximum_number_of_volumes );
380
381
43.7k
  data_offset = 184;
382
383
43.7k
  for( object_identifier_index = 0;
384
4.41M
       object_identifier_index < 100;
385
4.37M
       object_identifier_index++ )
386
4.37M
  {
387
4.37M
    byte_stream_copy_to_uint64_little_endian(
388
4.37M
     &( data[ data_offset ] ),
389
4.37M
     volume_object_identifier );
390
391
4.37M
    data_offset += 8;
392
393
4.37M
    container_superblock->volume_object_identifiers[ object_identifier_index ] = volume_object_identifier;
394
395
/* TODO what about non-consecutive volume object identifiers ?*/
396
4.37M
    if( volume_object_identifier != 0 )
397
111k
    {
398
111k
      container_superblock->number_of_volumes += 1;
399
111k
    }
400
4.37M
  }
401
43.7k
  if( memory_copy(
402
43.7k
       container_superblock->fusion_set_identifier,
403
43.7k
       ( (fsapfs_container_superblock_t *) data )->fusion_set_identifier,
404
43.7k
       16 ) == NULL )
405
0
  {
406
0
    libcerror_error_set(
407
0
     error,
408
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
409
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
410
0
     "%s: unable to copy Fusion set identifier.",
411
0
     function );
412
413
0
    return( -1 );
414
0
  }
415
43.7k
  byte_stream_copy_to_uint64_little_endian(
416
43.7k
   ( (fsapfs_container_superblock_t *) data )->key_bag_block_number,
417
43.7k
   container_superblock->key_bag_block_number );
418
419
43.7k
  byte_stream_copy_to_uint64_little_endian(
420
43.7k
   ( (fsapfs_container_superblock_t *) data )->key_bag_number_of_blocks,
421
43.7k
   container_superblock->key_bag_number_of_blocks );
422
423
43.7k
  byte_stream_copy_to_uint32_little_endian(
424
43.7k
   ( (fsapfs_container_superblock_t *) data )->checkpoint_descriptor_area_number_of_blocks,
425
43.7k
   container_superblock->checkpoint_descriptor_area_number_of_blocks );
426
427
43.7k
  byte_stream_copy_to_uint64_little_endian(
428
43.7k
   ( (fsapfs_container_superblock_t *) data )->checkpoint_descriptor_area_block_number,
429
43.7k
   container_superblock->checkpoint_descriptor_area_block_number );
430
431
43.7k
  byte_stream_copy_to_uint64_little_endian(
432
43.7k
   ( (fsapfs_container_superblock_t *) data )->fusion_middle_tree_block_number,
433
43.7k
   container_superblock->fusion_middle_tree_block_number );
434
435
#if defined( HAVE_DEBUG_OUTPUT )
436
  if( libcnotify_verbose != 0 )
437
  {
438
    libcnotify_printf(
439
     "%s: object checksum\t\t\t\t: 0x%08" PRIx64 "\n",
440
     function,
441
     stored_checksum );
442
443
    byte_stream_copy_to_uint64_little_endian(
444
     ( (fsapfs_container_superblock_t *) data )->object_identifier,
445
     value_64bit );
446
    libcnotify_printf(
447
     "%s: object identifier\t\t\t\t: %" PRIu64 "\n",
448
     function,
449
     value_64bit );
450
451
    libcnotify_printf(
452
     "%s: object transaction identifier\t\t\t: %" PRIu64 "\n",
453
     function,
454
     container_superblock->object_transaction_identifier );
455
456
    libcnotify_printf(
457
     "%s: object type\t\t\t\t\t: 0x%08" PRIx32 "\n",
458
     function,
459
     object_type );
460
461
    libcnotify_printf(
462
     "%s: object subtype\t\t\t\t: 0x%08" PRIx32 "\n",
463
     function,
464
     object_subtype );
465
466
    libcnotify_printf(
467
     "%s: signature\t\t\t\t\t: %c%c%c%c\n",
468
     function,
469
     ( (fsapfs_container_superblock_t *) data )->signature[ 0 ],
470
     ( (fsapfs_container_superblock_t *) data )->signature[ 1 ],
471
     ( (fsapfs_container_superblock_t *) data )->signature[ 2 ],
472
     ( (fsapfs_container_superblock_t *) data )->signature[ 3 ] );
473
474
    libcnotify_printf(
475
     "%s: block size\t\t\t\t\t: %" PRIu32 "\n",
476
     function,
477
     container_superblock->block_size );
478
479
    libcnotify_printf(
480
     "%s: number of blocks\t\t\t\t: %" PRIu64 "\n",
481
     function,
482
     container_superblock->number_of_blocks );
483
484
    byte_stream_copy_to_uint64_little_endian(
485
     ( (fsapfs_container_superblock_t *) data )->compatible_features_flags,
486
     value_64bit );
487
    libcnotify_printf(
488
     "%s: compatible features flags\t\t\t: 0x%08" PRIx64 "\n",
489
     function,
490
     value_64bit );
491
    libfsapfs_debug_print_container_compatible_features_flags(
492
     value_64bit );
493
    libcnotify_printf(
494
     "\n" );
495
496
    byte_stream_copy_to_uint64_little_endian(
497
     ( (fsapfs_container_superblock_t *) data )->read_only_compatible_features_flags,
498
     value_64bit );
499
    libcnotify_printf(
500
     "%s: read-only compatible features flags\t\t: 0x%08" PRIx64 "\n",
501
     function,
502
     value_64bit );
503
    libfsapfs_debug_print_container_read_only_compatible_features_flags(
504
     value_64bit );
505
    libcnotify_printf(
506
     "\n" );
507
508
    libcnotify_printf(
509
     "%s: incompatible features flags\t\t\t: 0x%08" PRIx64 "\n",
510
     function,
511
     container_superblock->incompatible_features_flags );
512
    libfsapfs_debug_print_container_incompatible_features_flags(
513
     container_superblock->incompatible_features_flags );
514
    libcnotify_printf(
515
     "\n" );
516
517
    if( libfsapfs_debug_print_guid_value(
518
         function,
519
         "container identifier\t\t\t\t",
520
         ( (fsapfs_container_superblock_t *) data )->container_identifier,
521
         16,
522
         LIBFGUID_ENDIAN_BIG,
523
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
524
         error ) != 1 )
525
    {
526
      libcerror_error_set(
527
       error,
528
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
529
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
530
       "%s: unable to print UUID value.",
531
       function );
532
533
      return( -1 );
534
    }
535
    byte_stream_copy_to_uint64_little_endian(
536
     ( (fsapfs_container_superblock_t *) data )->next_object_identifier,
537
     value_64bit );
538
    libcnotify_printf(
539
     "%s: next object identifier\t\t\t: %" PRIu64 "\n",
540
     function,
541
     value_64bit );
542
543
    byte_stream_copy_to_uint64_little_endian(
544
     ( (fsapfs_container_superblock_t *) data )->next_transaction_identifier,
545
     value_64bit );
546
    libcnotify_printf(
547
     "%s: next transaction identifier\t\t\t: %" PRIu64 "\n",
548
     function,
549
     value_64bit );
550
551
    libcnotify_printf(
552
     "%s: checkpoint descriptor area number of blocks\t: %" PRIu32 "\n",
553
     function,
554
     container_superblock->checkpoint_descriptor_area_number_of_blocks );
555
556
    byte_stream_copy_to_uint32_little_endian(
557
     ( (fsapfs_container_superblock_t *) data )->checkpoint_data_area_number_of_blocks,
558
     value_32bit );
559
    libcnotify_printf(
560
     "%s: checkpoint data area number of blocks\t\t: %" PRIu32 "\n",
561
     function,
562
     value_32bit );
563
564
    libcnotify_printf(
565
     "%s: checkpoint descriptor area block number\t: %" PRIu64 "\n",
566
     function,
567
     container_superblock->checkpoint_descriptor_area_block_number );
568
569
    byte_stream_copy_to_uint64_little_endian(
570
     ( (fsapfs_container_superblock_t *) data )->checkpoint_data_area_block_number,
571
     value_64bit );
572
    libcnotify_printf(
573
     "%s: checkpoint data area block number\t\t: %" PRIu64 "\n",
574
     function,
575
     value_64bit );
576
577
    byte_stream_copy_to_uint32_little_endian(
578
     ( (fsapfs_container_superblock_t *) data )->unknown8,
579
     value_32bit );
580
    libcnotify_printf(
581
     "%s: unknown8\t\t\t\t\t: 0x%08" PRIx32 "\n",
582
     function,
583
     value_32bit );
584
585
    byte_stream_copy_to_uint32_little_endian(
586
     ( (fsapfs_container_superblock_t *) data )->unknown9,
587
     value_32bit );
588
    libcnotify_printf(
589
     "%s: unknown9\t\t\t\t\t: 0x%08" PRIx32 "\n",
590
     function,
591
     value_32bit );
592
593
    byte_stream_copy_to_uint32_little_endian(
594
     ( (fsapfs_container_superblock_t *) data )->unknown10,
595
     value_32bit );
596
    libcnotify_printf(
597
     "%s: unknown10\t\t\t\t\t: %" PRIu32 "\n",
598
     function,
599
     value_32bit );
600
601
    byte_stream_copy_to_uint32_little_endian(
602
     ( (fsapfs_container_superblock_t *) data )->unknown11,
603
     value_32bit );
604
    libcnotify_printf(
605
     "%s: unknown11\t\t\t\t\t: 0x%08" PRIx32 "\n",
606
     function,
607
     value_32bit );
608
609
    byte_stream_copy_to_uint32_little_endian(
610
     ( (fsapfs_container_superblock_t *) data )->unknown12,
611
     value_32bit );
612
    libcnotify_printf(
613
     "%s: unknown12\t\t\t\t\t: 0x%08" PRIx32 "\n",
614
     function,
615
     value_32bit );
616
617
    byte_stream_copy_to_uint32_little_endian(
618
     ( (fsapfs_container_superblock_t *) data )->unknown13,
619
     value_32bit );
620
    libcnotify_printf(
621
     "%s: unknown13\t\t\t\t\t: %" PRIu32 "\n",
622
     function,
623
     value_32bit );
624
625
    libcnotify_printf(
626
     "%s: space manager object identifier\t\t: %" PRIu64 "\n",
627
     function,
628
     container_superblock->space_manager_object_identifier );
629
630
    libcnotify_printf(
631
     "%s: object map block number\t\t\t: %" PRIu64 "\n",
632
     function,
633
     container_superblock->object_map_block_number );
634
635
    libcnotify_printf(
636
     "%s: reaper object identifier\t\t\t: %" PRIu64 "\n",
637
     function,
638
     container_superblock->reaper_object_identifier );
639
640
    byte_stream_copy_to_uint32_little_endian(
641
     ( (fsapfs_container_superblock_t *) data )->unknown17,
642
     value_32bit );
643
    libcnotify_printf(
644
     "%s: unknown17\t\t\t\t\t: 0x%08" PRIx32 "\n",
645
     function,
646
     value_32bit );
647
648
    libcnotify_printf(
649
     "%s: maximum number of volumes\t\t\t: %" PRIu32 "\n",
650
     function,
651
     maximum_number_of_volumes );
652
653
    for( object_identifier_index = 0;
654
         object_identifier_index < 100;
655
         object_identifier_index++ )
656
    {
657
      if( container_superblock->volume_object_identifiers[ object_identifier_index ] != 0 )
658
      {
659
        libcnotify_printf(
660
         "%s: volume object identifier: %d\t\t\t: %" PRIu64 "\n",
661
         function,
662
         object_identifier_index,
663
         container_superblock->volume_object_identifiers[ object_identifier_index ] );
664
      }
665
    }
666
    for( counter_index = 0;
667
         counter_index < 32;
668
         counter_index++ )
669
    {
670
      byte_stream_copy_to_uint64_little_endian(
671
       &( ( (fsapfs_container_superblock_t *) data )->counters[ counter_index * 8 ] ),
672
       value_64bit );
673
674
      if( value_64bit != 0 )
675
      {
676
        libcnotify_printf(
677
         "%s: counter: %02d\t\t\t\t\t: 0x%08" PRIx64 "\n",
678
         function,
679
         counter_index,
680
         value_64bit );
681
      }
682
    }
683
    byte_stream_copy_to_uint64_little_endian(
684
     ( (fsapfs_container_superblock_t *) data )->unknown20,
685
     value_64bit );
686
    libcnotify_printf(
687
     "%s: unknown20\t\t\t\t\t: 0x%08" PRIx64 "\n",
688
     function,
689
     value_64bit );
690
691
    byte_stream_copy_to_uint64_little_endian(
692
     ( (fsapfs_container_superblock_t *) data )->unknown21,
693
     value_64bit );
694
    libcnotify_printf(
695
     "%s: unknown21\t\t\t\t\t: 0x%08" PRIx64 "\n",
696
     function,
697
     value_64bit );
698
699
    byte_stream_copy_to_uint64_little_endian(
700
     ( (fsapfs_container_superblock_t *) data )->unknown22,
701
     value_64bit );
702
    libcnotify_printf(
703
     "%s: unknown22\t\t\t\t\t: 0x%08" PRIx64 "\n",
704
     function,
705
     value_64bit );
706
707
    byte_stream_copy_to_uint64_little_endian(
708
     ( (fsapfs_container_superblock_t *) data )->unknown23,
709
     value_64bit );
710
    libcnotify_printf(
711
     "%s: unknown23\t\t\t\t\t: 0x%08" PRIx64 "\n",
712
     function,
713
     value_64bit );
714
715
    byte_stream_copy_to_uint64_little_endian(
716
     ( (fsapfs_container_superblock_t *) data )->unknown24,
717
     value_64bit );
718
    libcnotify_printf(
719
     "%s: unknown24\t\t\t\t\t: 0x%08" PRIx64 "\n",
720
     function,
721
     value_64bit );
722
723
    if( libfsapfs_debug_print_guid_value(
724
         function,
725
         "Fusion set identifier\t\t\t\t",
726
         ( (fsapfs_container_superblock_t *) data )->fusion_set_identifier,
727
         16,
728
         LIBFGUID_ENDIAN_BIG,
729
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
730
         error ) != 1 )
731
    {
732
      libcerror_error_set(
733
       error,
734
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
735
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
736
       "%s: unable to print UUID value.",
737
       function );
738
739
      return( -1 );
740
    }
741
    libcnotify_printf(
742
     "%s: key bag block number\t\t\t\t: %" PRIu64 "\n",
743
     function,
744
     container_superblock->key_bag_block_number );
745
746
    libcnotify_printf(
747
     "%s: key bag number of blocks\t\t\t: %" PRIu64 "\n",
748
     function,
749
     container_superblock->key_bag_number_of_blocks );
750
751
    libcnotify_printf(
752
     "%s: unknown29:\n",
753
     function );
754
    libcnotify_print_data(
755
     ( (fsapfs_container_superblock_t *) data )->unknown29,
756
     40,
757
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
758
759
    byte_stream_copy_to_uint64_little_endian(
760
     ( (fsapfs_container_superblock_t *) data )->unknown30,
761
     value_64bit );
762
    libcnotify_printf(
763
     "%s: unknown30\t\t\t\t\t: 0x%08" PRIx64 "\n",
764
     function,
765
     value_64bit );
766
767
    libcnotify_printf(
768
     "%s: Fusion middle tree block number\t\t: %" PRIu64 "\n",
769
     function,
770
     container_superblock->fusion_middle_tree_block_number );
771
772
    byte_stream_copy_to_uint64_little_endian(
773
     ( (fsapfs_container_superblock_t *) data )->fusion_write_back_cache_object_identifier,
774
     value_64bit );
775
    libcnotify_printf(
776
     "%s: Fusion write-back cache object identifier\t: %" PRIu64 "\n",
777
     function,
778
     value_64bit );
779
780
    byte_stream_copy_to_uint64_little_endian(
781
     ( (fsapfs_container_superblock_t *) data )->unknown33,
782
     value_64bit );
783
    libcnotify_printf(
784
     "%s: unknown33\t\t\t\t\t: 0x%08" PRIx64 "\n",
785
     function,
786
     value_64bit );
787
788
    byte_stream_copy_to_uint64_little_endian(
789
     ( (fsapfs_container_superblock_t *) data )->unknown34,
790
     value_64bit );
791
    libcnotify_printf(
792
     "%s: unknown34\t\t\t\t\t: 0x%08" PRIx64 "\n",
793
     function,
794
     value_64bit );
795
796
    libcnotify_printf(
797
     "\n" );
798
  }
799
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
800
801
43.7k
  if( libfsapfs_checksum_calculate_fletcher64(
802
43.7k
       &calculated_checksum,
803
43.7k
       &( data[ 8 ] ),
804
43.7k
       data_size - 8,
805
43.7k
       0,
806
43.7k
       error ) != 1 )
807
0
  {
808
0
    libcerror_error_set(
809
0
     error,
810
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
811
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
812
0
     "%s: unable to calculate Fletcher-64 checksum.",
813
0
     function );
814
815
0
    return( -1 );
816
0
  }
817
43.7k
  if( stored_checksum != calculated_checksum )
818
451
  {
819
451
    libcerror_error_set(
820
451
     error,
821
451
     LIBCERROR_ERROR_DOMAIN_INPUT,
822
451
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
823
451
     "%s: mismatch in checksum ( 0x%08" PRIx64 " != 0x%08" PRIx64 " ).\n",
824
451
     function,
825
451
     stored_checksum,
826
451
     calculated_checksum );
827
828
451
    return( -1 );
829
451
  }
830
43.2k
  if( ( container_superblock->incompatible_features_flags & 0x0000000000000001 ) != 0 )
831
4
  {
832
4
    libcerror_error_set(
833
4
     error,
834
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
835
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
836
4
     "%s: unsupported format version 1.",
837
4
     function );
838
839
4
    return( -1 );
840
4
  }
841
43.2k
  if( container_superblock->block_size != 4096 )
842
163
  {
843
163
    libcerror_error_set(
844
163
     error,
845
163
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
846
163
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
847
163
     "%s: unsupported block size: %" PRIu32 ".",
848
163
     function,
849
163
     container_superblock->block_size );
850
851
163
    return( -1 );
852
163
  }
853
43.1k
  if( ( container_superblock->checkpoint_descriptor_area_number_of_blocks & 0x80000000UL ) != 0 )
854
127
  {
855
127
    libcerror_error_set(
856
127
     error,
857
127
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
858
127
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
859
127
     "%s: unsupported checkpoint descriptor area number of blocks - MSB is set.",
860
127
     function );
861
862
127
    return( -1 );
863
127
  }
864
42.9k
  if( container_superblock->checkpoint_descriptor_area_block_number == 0 )
865
4
  {
866
4
    libcerror_error_set(
867
4
     error,
868
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
869
4
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
870
4
     "%s: unsupported checkpoint descriptor area block number: %" PRIu32 ".",
871
4
     function,
872
4
     container_superblock->checkpoint_descriptor_area_block_number );
873
874
4
    return( -1 );
875
4
  }
876
42.9k
  if( maximum_number_of_volumes > 100 )
877
51
  {
878
51
    libcerror_error_set(
879
51
     error,
880
51
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
881
51
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
882
51
     "%s: invalid number of volumes value out of bounds.",
883
51
     function );
884
885
51
    return( -1 );
886
51
  }
887
42.9k
  return( 1 );
888
42.9k
}
889
890
/* Retrieves the container identifier
891
 * The identifier is an UUID stored in big-endian and is 16 bytes of size
892
 * Returns 1 if successful or -1 on error
893
 */
894
int libfsapfs_container_superblock_get_container_identifier(
895
     libfsapfs_container_superblock_t *container_superblock,
896
     uint8_t *uuid_data,
897
     size_t uuid_data_size,
898
     libcerror_error_t **error )
899
0
{
900
0
  static char *function = "libfsapfs_container_superblock_get_container_identifier";
901
902
0
  if( container_superblock == NULL )
903
0
  {
904
0
    libcerror_error_set(
905
0
     error,
906
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
907
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
908
0
     "%s: invalid container superblock.",
909
0
     function );
910
911
0
    return( -1 );
912
0
  }
913
0
  if( uuid_data == NULL )
914
0
  {
915
0
    libcerror_error_set(
916
0
     error,
917
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
918
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
919
0
     "%s: invalid UUID data.",
920
0
     function );
921
922
0
    return( -1 );
923
0
  }
924
0
  if( ( uuid_data_size < 16 )
925
0
   || ( uuid_data_size > (size_t) SSIZE_MAX ) )
926
0
  {
927
0
    libcerror_error_set(
928
0
     error,
929
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
930
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
931
0
     "%s: invalid UUID data size value out of bounds.",
932
0
     function );
933
934
0
    return( -1 );
935
0
  }
936
0
  if( memory_copy(
937
0
       uuid_data,
938
0
       container_superblock->container_identifier,
939
0
       16 ) == NULL )
940
0
  {
941
0
    libcerror_error_set(
942
0
     error,
943
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
944
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
945
0
     "%s: unable to copy container identifier.",
946
0
     function );
947
948
0
    return( -1 );
949
0
  }
950
0
  return( 1 );
951
0
}
952