Coverage Report

Created: 2025-06-22 07:35

/src/libscca/libscca/libscca_io_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Input/Output (IO) handle functions
3
 *
4
 * Copyright (C) 2011-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 "libscca_compressed_block.h"
28
#include "libscca_debug.h"
29
#include "libscca_definitions.h"
30
#include "libscca_file_metrics.h"
31
#include "libscca_io_handle.h"
32
#include "libscca_libbfio.h"
33
#include "libscca_libcdata.h"
34
#include "libscca_libcerror.h"
35
#include "libscca_libcnotify.h"
36
#include "libscca_libfdatetime.h"
37
#include "libscca_libfvalue.h"
38
#include "libscca_libuna.h"
39
#include "libscca_unused.h"
40
#include "libscca_volume_information.h"
41
42
#include "scca_file_metrics_array.h"
43
#include "scca_trace_chain_array.h"
44
#include "scca_volume_information.h"
45
46
const char *scca_file_signature           = "SCCA";
47
const char *scca_mam_file_signature_win10 = "MAM\x04";
48
49
/* Creates an IO handle
50
 * Make sure the value io_handle is referencing, is set to NULL
51
 * Returns 1 if successful or -1 on error
52
 */
53
int libscca_io_handle_initialize(
54
     libscca_io_handle_t **io_handle,
55
     libcerror_error_t **error )
56
1.95k
{
57
1.95k
  static char *function = "libscca_io_handle_initialize";
58
59
1.95k
  if( io_handle == NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
64
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
65
0
     "%s: invalid IO handle.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
1.95k
  if( *io_handle != NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
75
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
76
0
     "%s: invalid IO handle value already set.",
77
0
     function );
78
79
0
    return( -1 );
80
0
  }
81
1.95k
  *io_handle = memory_allocate_structure(
82
1.95k
                libscca_io_handle_t );
83
84
1.95k
  if( *io_handle == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
90
0
     "%s: unable to create IO handle.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
1.95k
  if( memory_set(
96
1.95k
       *io_handle,
97
1.95k
       0,
98
1.95k
       sizeof( libscca_io_handle_t ) ) == NULL )
99
0
  {
100
0
    libcerror_error_set(
101
0
     error,
102
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
103
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
104
0
     "%s: unable to clear file.",
105
0
     function );
106
107
0
    goto on_error;
108
0
  }
109
1.95k
  return( 1 );
110
111
0
on_error:
112
0
  if( *io_handle != NULL )
113
0
  {
114
0
    memory_free(
115
0
     *io_handle );
116
117
0
    *io_handle = NULL;
118
0
  }
119
0
  return( -1 );
120
1.95k
}
121
122
/* Frees a IO handle
123
 * Returns 1 if successful or -1 on error
124
 */
125
int libscca_io_handle_free(
126
     libscca_io_handle_t **io_handle,
127
     libcerror_error_t **error )
128
1.95k
{
129
1.95k
  static char *function = "libscca_io_handle_free";
130
131
1.95k
  if( io_handle == NULL )
132
0
  {
133
0
    libcerror_error_set(
134
0
     error,
135
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
136
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
137
0
     "%s: invalid IO handle.",
138
0
     function );
139
140
0
    return( -1 );
141
0
  }
142
1.95k
  if( *io_handle != NULL )
143
1.95k
  {
144
1.95k
    memory_free(
145
1.95k
     *io_handle );
146
147
1.95k
    *io_handle = NULL;
148
1.95k
  }
149
1.95k
  return( 1 );
150
1.95k
}
151
152
/* Clears the IO handle
153
 * Returns 1 if successful or -1 on error
154
 */
155
int libscca_io_handle_clear(
156
     libscca_io_handle_t *io_handle,
157
     libcerror_error_t **error )
158
1.95k
{
159
1.95k
  static char *function = "libscca_io_handle_clear";
160
161
1.95k
  if( io_handle == 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 IO handle.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
1.95k
  if( memory_set(
173
1.95k
       io_handle,
174
1.95k
       0,
175
1.95k
       sizeof( libscca_io_handle_t ) ) == NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
180
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
181
0
     "%s: unable to clear IO handle.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
1.95k
  return( 1 );
187
1.95k
}
188
189
/* Reads the compressed file header
190
 * Returns 1 if successful or -1 on error
191
 */
192
int libscca_io_handle_read_compressed_file_header(
193
     libscca_io_handle_t *io_handle,
194
     libbfio_handle_t *file_io_handle,
195
     libcerror_error_t **error )
196
1.95k
{
197
1.95k
  uint8_t file_header_data[ 8 ];
198
199
1.95k
  static char *function = "libscca_io_handle_read_compressed_file_header";
200
1.95k
  size64_t file_size    = 0;
201
1.95k
  ssize_t read_count    = 0;
202
203
1.95k
  if( io_handle == NULL )
204
0
  {
205
0
    libcerror_error_set(
206
0
     error,
207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
209
0
     "%s: invalid IO handle.",
210
0
     function );
211
212
0
    return( -1 );
213
0
  }
214
1.95k
  if( libbfio_handle_get_size(
215
1.95k
       file_io_handle,
216
1.95k
       &file_size,
217
1.95k
       error ) != 1 )
218
0
  {
219
0
    libcerror_error_set(
220
0
     error,
221
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
223
0
     "%s: unable to retrieve file size.",
224
0
     function );
225
226
0
    return( -1 );
227
0
  }
228
1.95k
  if( ( file_size < 8 )
229
1.95k
   || ( file_size > (size64_t) UINT32_MAX ) )
230
4
  {
231
4
    libcerror_error_set(
232
4
     error,
233
4
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
234
4
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
235
4
     "%s: invalid file size value out of bounds.",
236
4
     function );
237
238
4
    return( -1 );
239
4
  }
240
1.95k
  io_handle->file_size = (uint32_t) file_size;
241
242
#if defined( HAVE_DEBUG_OUTPUT )
243
  if( libcnotify_verbose != 0 )
244
  {
245
    libcnotify_printf(
246
     "%s: reading compressed file header at offset: 0 (0x00000000)\n",
247
     function );
248
  }
249
#endif
250
1.95k
  read_count = libbfio_handle_read_buffer_at_offset(
251
1.95k
                file_io_handle,
252
1.95k
                file_header_data,
253
1.95k
                8,
254
1.95k
                0,
255
1.95k
                error );
256
257
1.95k
  if( read_count != (ssize_t) 8 )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_IO,
262
0
     LIBCERROR_IO_ERROR_READ_FAILED,
263
0
     "%s: unable to read file header data at offset: 0 (0x00000000).",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
1.95k
  if( memory_compare(
269
1.95k
       &( file_header_data[ 4 ] ),
270
1.95k
       scca_file_signature,
271
1.95k
       4 ) == 0 )
272
1.50k
  {
273
1.50k
    io_handle->file_type= LIBSCCA_FILE_TYPE_UNCOMPRESSED;
274
1.50k
  }
275
450
  else if( memory_compare(
276
450
            file_header_data,
277
450
            scca_mam_file_signature_win10,
278
450
            4 ) == 0 )
279
420
  {
280
420
    io_handle->file_type = LIBSCCA_FILE_TYPE_COMPRESSED_WINDOWS10;
281
420
  }
282
30
  else
283
30
  {
284
30
    libcerror_error_set(
285
30
     error,
286
30
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
287
30
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
288
30
     "%s: unsupported signature.",
289
30
     function );
290
291
30
    return( -1 );
292
30
  }
293
1.92k
  if( io_handle->file_type == LIBSCCA_FILE_TYPE_UNCOMPRESSED )
294
1.50k
  {
295
1.50k
    io_handle->uncompressed_data_size = io_handle->file_size;
296
1.50k
  }
297
420
  else if( io_handle->file_type == LIBSCCA_FILE_TYPE_COMPRESSED_WINDOWS10 )
298
420
  {
299
#if defined( HAVE_DEBUG_OUTPUT )
300
    if( libcnotify_verbose != 0 )
301
    {
302
      libcnotify_printf(
303
       "%s: signature\t\t: %c%c%c\\x%02x\n",
304
       function,
305
       file_header_data[ 0 ],
306
       file_header_data[ 1 ],
307
       file_header_data[ 2 ],
308
       file_header_data[ 3 ] );
309
    }
310
#endif
311
420
    byte_stream_copy_to_uint32_little_endian(
312
420
     &( file_header_data[ 4 ] ),
313
420
     io_handle->uncompressed_data_size );
314
315
#if defined( HAVE_DEBUG_OUTPUT )
316
    if( libcnotify_verbose != 0 )
317
    {
318
      libcnotify_printf(
319
       "%s: uncompressed data size\t: %" PRIu32 "\n",
320
       function,
321
       io_handle->uncompressed_data_size );
322
    }
323
#endif
324
420
    if( io_handle->uncompressed_data_size != ( io_handle->file_size - 8 )  )
325
419
    {
326
/* TODO flag mismatch and file as corrupted? */
327
419
    }
328
420
  }
329
#if defined( HAVE_DEBUG_OUTPUT )
330
  if( libcnotify_verbose != 0 )
331
  {
332
    libcnotify_printf(
333
     "\n" );
334
  }
335
#endif
336
1.92k
  return( 1 );
337
1.95k
}
338
339
/* Reads the compressed blocks
340
 * Returns 1 if successful or -1 on error
341
 */
342
int libscca_io_handle_read_compressed_blocks(
343
     libscca_io_handle_t *io_handle,
344
     libbfio_handle_t *file_io_handle,
345
     libfdata_list_t *compressed_blocks_list,
346
     libfcache_cache_t *compressed_blocks_cache,
347
     libcerror_error_t **error )
348
420
{
349
420
  libfdata_list_element_t *compressed_blocks_list_element = NULL;
350
420
  libscca_compressed_block_t *compressed_block            = NULL;
351
420
  static char *function                                   = "libscca_io_handle_read_compressed_blocks";
352
420
  off64_t file_offset                                     = 0;
353
420
  size64_t compressed_data_size                           = 0;
354
420
  ssize_t read_count                                      = 0;
355
420
  uint32_t uncompressed_data_size                         = 0;
356
420
  uint32_t uncompressed_block_size                        = 0;
357
420
  int compressed_block_index                              = 0;
358
420
  int element_index                                       = 0;
359
360
420
  if( io_handle == NULL )
361
0
  {
362
0
    libcerror_error_set(
363
0
     error,
364
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
365
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
366
0
     "%s: invalid IO handle.",
367
0
     function );
368
369
0
    return( -1 );
370
0
  }
371
420
  if( io_handle->file_type != LIBSCCA_FILE_TYPE_COMPRESSED_WINDOWS10 )
372
0
  {
373
0
    libcerror_error_set(
374
0
     error,
375
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
376
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
377
0
     "%s: invalid IO handle - unsupported file type.",
378
0
     function );
379
380
0
    return( -1 );
381
0
  }
382
420
  file_offset = 8;
383
384
420
  uncompressed_data_size = io_handle->uncompressed_data_size;
385
420
  compressed_data_size   = io_handle->file_size - 8;
386
387
559
  while( compressed_data_size > 2 )
388
418
  {
389
418
    uncompressed_block_size = (size_t) uncompressed_data_size;
390
391
418
    if( libscca_compressed_block_initialize(
392
418
         &compressed_block,
393
418
         uncompressed_block_size,
394
418
         error ) != 1 )
395
12
    {
396
12
      libcerror_error_set(
397
12
       error,
398
12
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
399
12
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
400
12
       "%s: unable to create compressed block.",
401
12
       function );
402
403
12
      goto on_error;
404
12
    }
405
#if defined( HAVE_DEBUG_OUTPUT )
406
    if( libcnotify_verbose != 0 )
407
    {
408
      libcnotify_printf(
409
       "%s: reading compressed data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
410
       function,
411
       file_offset,
412
       file_offset );
413
    }
414
#endif
415
406
    read_count = libscca_compressed_block_read_file_io_handle(
416
406
                  compressed_block,
417
406
                  file_io_handle,
418
406
                  file_offset,
419
406
                  (size_t) uncompressed_block_size,
420
406
                  error );
421
422
406
    if( read_count == -1 )
423
267
    {
424
267
      libcerror_error_set(
425
267
       error,
426
267
       LIBCERROR_ERROR_DOMAIN_IO,
427
267
       LIBCERROR_IO_ERROR_READ_FAILED,
428
267
       "%s: unable to read compressed block data.",
429
267
       function );
430
431
267
      goto on_error;
432
267
    }
433
#if defined( HAVE_DEBUG_OUTPUT )
434
    if( libcnotify_verbose != 0 )
435
    {
436
      libcnotify_printf(
437
       "%s: compressed block: %d size\t: %" PRIu32 "\n",
438
       function,
439
       compressed_block_index,
440
       compressed_block->data_size );
441
    }
442
#endif
443
139
    if( libfdata_list_append_element_with_mapped_size(
444
139
         compressed_blocks_list,
445
139
         &element_index,
446
139
         0,
447
139
         file_offset,
448
139
         (size64_t) read_count,
449
139
         LIBFDATA_RANGE_FLAG_IS_COMPRESSED,
450
139
         compressed_block->data_size,
451
139
         error ) != 1 )
452
0
    {
453
0
      libcerror_error_set(
454
0
       error,
455
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
457
0
       "%s: unable to append compressed block: %d to list.",
458
0
       function,
459
0
       compressed_block_index );
460
461
0
      goto on_error;
462
0
    }
463
139
    file_offset            += read_count;
464
139
    compressed_data_size   -= read_count;
465
139
    uncompressed_data_size -= uncompressed_block_size;
466
467
139
    if( libfdata_list_get_list_element_by_index(
468
139
         compressed_blocks_list,
469
139
         element_index,
470
139
         &compressed_blocks_list_element,
471
139
         error ) != 1 )
472
0
    {
473
0
      libcerror_error_set(
474
0
       error,
475
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
477
0
       "%s: unable to retrieve compressed block: %d list element.",
478
0
       function,
479
0
       element_index );
480
481
0
      goto on_error;
482
0
    }
483
139
    if( libfdata_list_element_set_element_value(
484
139
         compressed_blocks_list_element,
485
139
         (intptr_t *) file_io_handle,
486
139
         (libfdata_cache_t *) compressed_blocks_cache,
487
139
         (intptr_t *) compressed_block,
488
139
         (int (*)(intptr_t **, libcerror_error_t **)) &libscca_compressed_block_free,
489
139
         LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
490
139
         error ) != 1 )
491
0
    {
492
0
      libcerror_error_set(
493
0
       error,
494
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
496
0
       "%s: unable to set compressed block: %d as element value.",
497
0
       function,
498
0
       element_index );
499
500
0
      goto on_error;
501
0
    }
502
139
    compressed_block = NULL;
503
504
139
    compressed_block_index++;
505
139
  }
506
141
  return( 1 );
507
508
279
on_error:
509
279
  if( compressed_block != NULL )
510
267
  {
511
267
    libscca_compressed_block_free(
512
267
     &compressed_block,
513
267
     NULL );
514
267
  }
515
279
  return( -1 );
516
420
}
517
518
/* Reads the file metrics array
519
 * Returns 1 if successful or -1 on error
520
 */
521
int libscca_io_handle_read_file_metrics_array(
522
     libscca_io_handle_t *io_handle,
523
     libfdata_stream_t *uncompressed_data_stream,
524
     libbfio_handle_t *file_io_handle,
525
     uint32_t file_offset,
526
     uint32_t number_of_entries,
527
     libscca_filename_strings_t *filename_strings,
528
     libcdata_array_t *file_metrics_array,
529
     libcerror_error_t **error )
530
277
{
531
277
  libscca_file_metrics_t *file_metrics = NULL;
532
277
  uint8_t *entry_data                  = NULL;
533
277
  uint8_t *file_metrics_array_data     = NULL;
534
277
  static char *function                = "libscca_io_handle_read_file_metrics_array";
535
277
  size_t entry_data_size               = 0;
536
277
  size_t read_size                     = 0;
537
277
  ssize_t read_count                   = 0;
538
277
  uint32_t file_metrics_entry_index    = 0;
539
277
  int entry_index                      = 0;
540
541
277
  if( io_handle == NULL )
542
0
  {
543
0
    libcerror_error_set(
544
0
     error,
545
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
546
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
547
0
     "%s: invalid IO handle.",
548
0
     function );
549
550
0
    return( -1 );
551
0
  }
552
277
  if( io_handle->format_version == 17 )
553
227
  {
554
227
    entry_data_size = sizeof( scca_file_metrics_array_entry_v17_t );
555
227
  }
556
50
  else if( ( io_handle->format_version == 23 )
557
50
        || ( io_handle->format_version == 26 )
558
50
        || ( io_handle->format_version == 30 )
559
50
        || ( io_handle->format_version == 31 ) )
560
50
  {
561
50
    entry_data_size = sizeof( scca_file_metrics_array_entry_v23_t );
562
50
  }
563
0
  else
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
568
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
569
0
     "%s: invalid IO handle - unsupported format version.",
570
0
     function );
571
572
0
    return( -1 );
573
0
  }
574
277
  if( ( number_of_entries == 0 )
575
277
   || ( (size_t) number_of_entries > ( (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / entry_data_size ) ) )
576
50
  {
577
50
    libcerror_error_set(
578
50
     error,
579
50
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
50
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
581
50
     "%s: invalid number of entries value out of bounds.",
582
50
     function );
583
584
50
    return( -1 );
585
50
  }
586
227
  read_size = number_of_entries * entry_data_size;
587
588
227
  file_metrics_array_data = (uint8_t *) memory_allocate(
589
227
                                         sizeof( uint8_t ) * read_size );
590
591
227
  if( file_metrics_array_data == NULL )
592
0
  {
593
0
    libcerror_error_set(
594
0
     error,
595
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
596
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
597
0
     "%s: unable to create file metrics array data.",
598
0
     function );
599
600
0
    goto on_error;
601
0
  }
602
#if defined( HAVE_DEBUG_OUTPUT )
603
  if( libcnotify_verbose != 0 )
604
  {
605
    libcnotify_printf(
606
     "%s: reading file metrics array at offset: %" PRIu32 " (0x%08" PRIx32 ")\n",
607
     function,
608
     file_offset,
609
     file_offset );
610
  }
611
#endif
612
227
  read_count = libfdata_stream_read_buffer_at_offset(
613
227
                uncompressed_data_stream,
614
227
                (intptr_t *) file_io_handle,
615
227
                file_metrics_array_data,
616
227
                read_size,
617
227
                (off64_t) file_offset,
618
227
                0,
619
227
                error );
620
621
227
  if( read_count != (ssize_t) read_size )
622
106
  {
623
106
    libcerror_error_set(
624
106
     error,
625
106
     LIBCERROR_ERROR_DOMAIN_IO,
626
106
     LIBCERROR_IO_ERROR_READ_FAILED,
627
106
     "%s: unable to read file metrics array data at offset: %" PRIu32 " (0x%08" PRIx32 ").",
628
106
     function,
629
106
     file_offset,
630
106
     file_offset );
631
632
106
    goto on_error;
633
106
  }
634
#if defined( HAVE_DEBUG_OUTPUT )
635
  if( libcnotify_verbose != 0 )
636
  {
637
    libcnotify_printf(
638
     "%s: file metrics array data:\n",
639
     function );
640
    libcnotify_print_data(
641
     file_metrics_array_data,
642
     read_size,
643
     0 );
644
  }
645
#endif
646
121
  entry_data = file_metrics_array_data;
647
648
121
  for( file_metrics_entry_index = 0;
649
239k
       file_metrics_entry_index < number_of_entries;
650
239k
       file_metrics_entry_index++ )
651
239k
  {
652
239k
    if( libscca_file_metrics_initialize(
653
239k
         &file_metrics,
654
239k
         filename_strings,
655
239k
         error ) != 1 )
656
0
    {
657
0
      libcerror_error_set(
658
0
       error,
659
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
660
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
661
0
       "%s: unable to create file metrics: %" PRIu32 ".",
662
0
       function,
663
0
       file_metrics_entry_index );
664
665
0
      goto on_error;
666
0
    }
667
239k
    if( libscca_file_metrics_read_data(
668
239k
         file_metrics,
669
239k
         io_handle,
670
239k
         entry_data,
671
239k
         entry_data_size,
672
239k
         error ) != 1 )
673
0
    {
674
0
      libcerror_error_set(
675
0
       error,
676
0
       LIBCERROR_ERROR_DOMAIN_IO,
677
0
       LIBCERROR_IO_ERROR_READ_FAILED,
678
0
       "%s: unable to read file metrics: %" PRIu32 ".",
679
0
       function,
680
0
       file_metrics_entry_index );
681
682
0
      goto on_error;
683
0
    }
684
239k
    entry_data += entry_data_size;
685
686
239k
    if( libcdata_array_append_entry(
687
239k
         file_metrics_array,
688
239k
         &entry_index,
689
239k
         (intptr_t *) file_metrics,
690
239k
         error ) != 1 )
691
0
    {
692
0
      libcerror_error_set(
693
0
       error,
694
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
695
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
696
0
       "%s: unable to append file metrics: %" PRIu32 " to array.",
697
0
       function,
698
0
       file_metrics_entry_index );
699
700
0
      goto on_error;
701
0
    }
702
239k
    file_metrics = NULL;
703
239k
  }
704
121
  memory_free(
705
121
   file_metrics_array_data );
706
707
121
  return( 1 );
708
709
106
on_error:
710
106
  if( file_metrics != NULL )
711
0
  {
712
0
    libscca_internal_file_metrics_free(
713
0
     (libscca_internal_file_metrics_t **) &file_metrics,
714
0
     NULL );
715
0
  }
716
106
  if( file_metrics_array_data != NULL )
717
106
  {
718
106
    memory_free(
719
106
     file_metrics_array_data );
720
106
  }
721
106
  return( -1 );
722
121
}
723
724
/* Reads the trace chain array
725
 * Returns 1 if successful or -1 on error
726
 */
727
int libscca_io_handle_read_trace_chain_array(
728
     libscca_io_handle_t *io_handle,
729
     libfdata_stream_t *uncompressed_data_stream,
730
     libbfio_handle_t *file_io_handle,
731
     uint32_t file_offset,
732
     uint32_t number_of_entries,
733
     libcerror_error_t **error )
734
0
{
735
0
  uint8_t *entry_data             = NULL;
736
0
  uint8_t *trace_chain_array_data = NULL;
737
0
  static char *function           = "libscca_io_handle_read_trace_chain_array";
738
0
  size_t entry_data_size          = 0;
739
0
  size_t read_size                = 0;
740
0
  ssize_t read_count              = 0;
741
0
  uint32_t entry_index            = 0;
742
0
  uint32_t next_table_index       = 0;
743
744
#if defined( HAVE_DEBUG_OUTPUT )
745
  uint32_t value_32bit            = 0;
746
  uint16_t value_16bit            = 0;
747
#endif
748
749
0
  if( io_handle == NULL )
750
0
  {
751
0
    libcerror_error_set(
752
0
     error,
753
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
754
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
755
0
     "%s: invalid IO handle.",
756
0
     function );
757
758
0
    return( -1 );
759
0
  }
760
0
  if( ( io_handle->format_version == 17 )
761
0
   || ( io_handle->format_version == 23 )
762
0
   || ( io_handle->format_version == 26 ) )
763
0
  {
764
0
    entry_data_size = sizeof( scca_trace_chain_array_entry_v17_t );
765
0
  }
766
0
  else if( ( io_handle->format_version == 30 )
767
0
        || ( io_handle->format_version == 31 ) )
768
0
  {
769
0
    entry_data_size = sizeof( scca_trace_chain_array_entry_v30_t );
770
0
  }
771
0
  else
772
0
  {
773
0
    libcerror_error_set(
774
0
     error,
775
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
776
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
777
0
     "%s: invalid IO handle - unsupported format version.",
778
0
     function );
779
780
0
    return( -1 );
781
0
  }
782
0
  if( ( number_of_entries == 0 )
783
0
   || ( (size_t) number_of_entries > ( (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE / entry_data_size ) ) )
784
0
  {
785
0
    libcerror_error_set(
786
0
     error,
787
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
788
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
789
0
     "%s: invalid number of entries value out of bounds.",
790
0
     function );
791
792
0
    return( -1 );
793
0
  }
794
0
  read_size = number_of_entries * entry_data_size;
795
796
0
  trace_chain_array_data = (uint8_t *) memory_allocate(
797
0
                                        sizeof( uint8_t ) * read_size );
798
799
0
  if( trace_chain_array_data == NULL )
800
0
  {
801
0
    libcerror_error_set(
802
0
     error,
803
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
804
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
805
0
     "%s: unable to create trace chain array data.",
806
0
     function );
807
808
0
    goto on_error;
809
0
  }
810
#if defined( HAVE_DEBUG_OUTPUT )
811
  if( libcnotify_verbose != 0 )
812
  {
813
    libcnotify_printf(
814
     "%s: reading trace chain array at offset: %" PRIu32 " (0x%08" PRIx32 ")\n",
815
     function,
816
     file_offset,
817
     file_offset );
818
  }
819
#endif
820
0
  read_count = libfdata_stream_read_buffer_at_offset(
821
0
                uncompressed_data_stream,
822
0
                (intptr_t *) file_io_handle,
823
0
                trace_chain_array_data,
824
0
                read_size,
825
0
                (off64_t) file_offset,
826
0
                0,
827
0
                error );
828
829
0
  if( read_count != (ssize_t) read_size )
830
0
  {
831
0
    libcerror_error_set(
832
0
     error,
833
0
     LIBCERROR_ERROR_DOMAIN_IO,
834
0
     LIBCERROR_IO_ERROR_READ_FAILED,
835
0
     "%s: unable to read trace chain array data at offset: %" PRIu32 " (0x%08" PRIx32 ").",
836
0
     function,
837
0
     file_offset,
838
0
     file_offset );
839
840
0
    goto on_error;
841
0
  }
842
#if defined( HAVE_DEBUG_OUTPUT )
843
  if( libcnotify_verbose != 0 )
844
  {
845
    libcnotify_printf(
846
     "%s: trace chain array data:\n",
847
     function );
848
    libcnotify_print_data(
849
     trace_chain_array_data,
850
     read_size,
851
     0 );
852
  }
853
#endif
854
0
  entry_data = trace_chain_array_data;
855
856
0
  for( entry_index = 0;
857
0
       entry_index < number_of_entries;
858
0
       entry_index++ )
859
0
  {
860
#if defined( HAVE_DEBUG_OUTPUT )
861
    if( libcnotify_verbose != 0 )
862
    {
863
      libcnotify_printf(
864
       "%s: trace chain array entry: %" PRIu32 " data:\n",
865
       function,
866
       entry_index );
867
      libcnotify_print_data(
868
       entry_data,
869
       entry_data_size,
870
       0 );
871
    }
872
#endif
873
0
    if( entry_data_size == 8 )
874
0
    {
875
#if defined( HAVE_DEBUG_OUTPUT )
876
      if( libcnotify_verbose != 0 )
877
      {
878
        byte_stream_copy_to_uint32_little_endian(
879
         ( (scca_trace_chain_array_entry_v30_t *) entry_data )->total_block_load_count,
880
         value_32bit );
881
        libcnotify_printf(
882
         "%s: total block load count\t: %" PRIu32 " blocks (%" PRIu64 " bytes)\n",
883
         function,
884
         value_32bit,
885
         (uint64_t) value_32bit * 512 * 1024 );
886
887
        libcnotify_printf(
888
         "%s: unknown1\t\t\t: 0x%02" PRIx8 "\n",
889
         function,
890
         ( (scca_trace_chain_array_entry_v30_t *) entry_data )->unknown1 );
891
892
        libcnotify_printf(
893
         "%s: unknown2\t\t\t: 0x%02" PRIx8 "\n",
894
         function,
895
         ( (scca_trace_chain_array_entry_v30_t *) entry_data )->unknown2 );
896
897
        byte_stream_copy_to_uint16_little_endian(
898
         ( (scca_trace_chain_array_entry_v30_t *) entry_data )->unknown3,
899
         value_16bit );
900
        libcnotify_printf(
901
         "%s: unknown3\t\t\t: 0x%04" PRIx16 "\n",
902
         function,
903
         value_16bit );
904
      }
905
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
906
0
    }
907
0
    else if( entry_data_size == 12 )
908
0
    {
909
0
      byte_stream_copy_to_uint32_little_endian(
910
0
       ( (scca_trace_chain_array_entry_v17_t *) entry_data )->next_array_entry_index,
911
0
       next_table_index );
912
913
#if defined( HAVE_DEBUG_OUTPUT )
914
      if( libcnotify_verbose != 0 )
915
      {
916
        if( next_table_index == 0xffffffffUL )
917
        {
918
          libcnotify_printf(
919
           "%s: next table index\t\t: 0x%08" PRIx32 "\n",
920
           function,
921
           next_table_index );
922
        }
923
        else
924
        {
925
          libcnotify_printf(
926
           "%s: next table index\t\t: %" PRIu32 "\n",
927
           function,
928
           next_table_index );
929
        }
930
        byte_stream_copy_to_uint32_little_endian(
931
         ( (scca_trace_chain_array_entry_v17_t *) entry_data )->total_block_load_count,
932
         value_32bit );
933
        libcnotify_printf(
934
         "%s: total block load count\t: %" PRIu32 " blocks (%" PRIu64 " bytes)\n",
935
         function,
936
         value_32bit,
937
         (uint64_t) value_32bit * 512 * 1024 );
938
939
        libcnotify_printf(
940
         "%s: unknown1\t\t\t: 0x%02" PRIx8 "\n",
941
         function,
942
         ( (scca_trace_chain_array_entry_v17_t *) entry_data )->unknown1 );
943
944
        libcnotify_printf(
945
         "%s: unknown2\t\t\t: 0x%02" PRIx8 "\n",
946
         function,
947
         ( (scca_trace_chain_array_entry_v17_t *) entry_data )->unknown2 );
948
949
        byte_stream_copy_to_uint16_little_endian(
950
         ( (scca_trace_chain_array_entry_v17_t *) entry_data )->unknown3,
951
         value_16bit );
952
        libcnotify_printf(
953
         "%s: unknown3\t\t\t: 0x%04" PRIx16 "\n",
954
         function,
955
         value_16bit );
956
      }
957
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
958
0
    }
959
#if defined( HAVE_DEBUG_OUTPUT )
960
    if( libcnotify_verbose != 0 )
961
    {
962
      libcnotify_printf(
963
       "\n" );
964
    }
965
#endif
966
0
    entry_data += entry_data_size;
967
0
  }
968
0
  memory_free(
969
0
   trace_chain_array_data );
970
971
0
  return( 1 );
972
973
0
on_error:
974
0
  if( trace_chain_array_data != NULL )
975
0
  {
976
0
    memory_free(
977
0
     trace_chain_array_data );
978
0
  }
979
0
  return( -1 );
980
0
}
981
982
/* Reads the volumes information
983
 * Returns 1 if successful or -1 on error
984
 */
985
int libscca_io_handle_read_volumes_information(
986
     libscca_io_handle_t *io_handle,
987
     libfdata_stream_t *uncompressed_data_stream,
988
     libbfio_handle_t *file_io_handle,
989
     uint32_t volumes_information_offset,
990
     uint32_t volumes_information_size,
991
     uint32_t number_of_volumes,
992
     libcdata_array_t *volumes_array,
993
     libcerror_error_t **error )
994
711
{
995
711
  libscca_internal_volume_information_t *volume_information = NULL;
996
711
  uint8_t *volume_information_data                          = NULL;
997
711
  uint8_t *volumes_information_data                         = NULL;
998
711
  static char *function                                     = "libscca_io_handle_read_volumes_information";
999
711
  size_t directory_string_size                              = 0;
1000
711
  ssize_t read_count                                        = 0;
1001
711
  ssize_t volume_information_size                           = 0;
1002
711
  uint32_t device_path_offset                               = 0;
1003
711
  uint32_t device_path_size                                 = 0;
1004
711
  uint32_t directory_string_index                           = 0;
1005
711
  uint32_t directory_string_offset                          = 0;
1006
711
  uint32_t directory_strings_array_offset                   = 0;
1007
711
  uint32_t file_references_offset                           = 0;
1008
711
  uint32_t file_references_size                             = 0;
1009
711
  uint32_t number_of_directory_strings                      = 0;
1010
711
  uint32_t number_of_file_references                        = 0;
1011
711
  uint32_t version                                          = 0;
1012
711
  uint32_t volume_index                                     = 0;
1013
711
  uint32_t volume_information_offset                        = 0;
1014
711
  uint16_t number_of_characters                             = 0;
1015
711
  int entry_index                                           = 0;
1016
1017
#if defined( HAVE_DEBUG_OUTPUT )
1018
  uint64_t value_64bit                                      = 0;
1019
  uint32_t value_32bit                                      = 0;
1020
  uint32_t file_references_index                            = 0;
1021
#endif
1022
1023
711
  if( io_handle == NULL )
1024
0
  {
1025
0
    libcerror_error_set(
1026
0
     error,
1027
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1028
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1029
0
     "%s: invalid IO handle.",
1030
0
     function );
1031
1032
0
    return( -1 );
1033
0
  }
1034
711
  if( ( io_handle->format_version != 17 )
1035
711
   && ( io_handle->format_version != 23 )
1036
711
   && ( io_handle->format_version != 26 )
1037
711
   && ( io_handle->format_version != 30 )
1038
711
   && ( io_handle->format_version != 31 ) )
1039
0
  {
1040
0
    libcerror_error_set(
1041
0
     error,
1042
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1043
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
1044
0
     "%s: invalid IO handle - unsupported format version.",
1045
0
     function );
1046
1047
0
    return( -1 );
1048
0
  }
1049
711
  if( ( volumes_information_size < 2 )
1050
711
   || ( volumes_information_size > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1051
24
  {
1052
24
    libcerror_error_set(
1053
24
     error,
1054
24
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1055
24
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1056
24
     "%s: invalid volumes information size value out of bounds.",
1057
24
     function );
1058
1059
24
    goto on_error;
1060
24
  }
1061
687
  if( ( number_of_volumes == 0 )
1062
687
   || ( number_of_volumes > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1063
46
  {
1064
46
    libcerror_error_set(
1065
46
     error,
1066
46
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1067
46
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1068
46
     "%s: invalid number of volumes value out of bounds.",
1069
46
     function );
1070
1071
46
    return( -1 );
1072
46
  }
1073
641
  volumes_information_data = (uint8_t *) memory_allocate(
1074
641
                                          sizeof( uint8_t ) * volumes_information_size );
1075
1076
641
  if( volumes_information_data == NULL )
1077
0
  {
1078
0
    libcerror_error_set(
1079
0
     error,
1080
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1081
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1082
0
     "%s: unable to create volumes information data.",
1083
0
     function );
1084
1085
0
    goto on_error;
1086
0
  }
1087
#if defined( HAVE_DEBUG_OUTPUT )
1088
  if( libcnotify_verbose != 0 )
1089
  {
1090
    libcnotify_printf(
1091
     "%s: reading volumes information at offset: %" PRIi32 " (0x%08" PRIx32 ")\n",
1092
     function,
1093
     volumes_information_offset,
1094
     volumes_information_offset );
1095
  }
1096
#endif
1097
641
  read_count = libfdata_stream_read_buffer_at_offset(
1098
641
                uncompressed_data_stream,
1099
641
                (intptr_t *) file_io_handle,
1100
641
                volumes_information_data,
1101
641
                volumes_information_size,
1102
641
                (off64_t) volumes_information_offset,
1103
641
                0,
1104
641
                error );
1105
1106
641
  if( read_count != (ssize_t) volumes_information_size )
1107
0
  {
1108
0
    libcerror_error_set(
1109
0
     error,
1110
0
     LIBCERROR_ERROR_DOMAIN_IO,
1111
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1112
0
     "%s: unable to read volumes information data at offset: %" PRIi32 " (0x%08" PRIx32 ").",
1113
0
     function,
1114
0
     volumes_information_offset,
1115
0
     volumes_information_offset );
1116
1117
0
    goto on_error;
1118
0
  }
1119
#if defined( HAVE_DEBUG_OUTPUT )
1120
  if( libcnotify_verbose != 0 )
1121
  {
1122
    libcnotify_printf(
1123
     "%s: volumes information data:\n",
1124
     function,
1125
     volume_index );
1126
    libcnotify_print_data(
1127
     volumes_information_data,
1128
     volumes_information_size,
1129
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1130
  }
1131
#endif
1132
641
  if( io_handle->format_version == 17 )
1133
630
  {
1134
630
    volume_information_size = sizeof( scca_volume_information_v17_t );
1135
630
  }
1136
11
  else if( ( io_handle->format_version == 23 )
1137
11
        || ( io_handle->format_version == 26 ) )
1138
9
  {
1139
9
    volume_information_size = sizeof( scca_volume_information_v23_t );
1140
9
  }
1141
2
  else if( ( io_handle->format_version == 30 )
1142
2
        || ( io_handle->format_version == 31 ) )
1143
2
  {
1144
2
    volume_information_size = sizeof( scca_volume_information_v30_t );
1145
2
  }
1146
641
  if( volume_information_size > volumes_information_size )
1147
54
  {
1148
54
    libcerror_error_set(
1149
54
     error,
1150
54
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151
54
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1152
54
     "%s: invalid volume information size value out of bounds.",
1153
54
     function );
1154
1155
54
    goto on_error;
1156
54
  }
1157
587
  for( volume_index = 0;
1158
4.83k
       volume_index < number_of_volumes;
1159
4.24k
       volume_index++ )
1160
4.83k
  {
1161
4.83k
    if( libscca_volume_information_initialize(
1162
4.83k
         (libscca_volume_information_t **) &volume_information,
1163
4.83k
         error ) != 1 )
1164
0
    {
1165
0
      libcerror_error_set(
1166
0
       error,
1167
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1168
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1169
0
       "%s: unable to create volume: %" PRIu32 " information.",
1170
0
       function,
1171
0
       volume_index );
1172
1173
0
      goto on_error;
1174
0
    }
1175
4.83k
    if( volume_information_offset > ( volumes_information_size - volume_information_size ) )
1176
51
    {
1177
51
      libcerror_error_set(
1178
51
       error,
1179
51
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1180
51
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1181
51
       "%s: invalid volume information offset value out of bounds.",
1182
51
       function );
1183
1184
51
      goto on_error;
1185
51
    }
1186
#if defined( HAVE_DEBUG_OUTPUT )
1187
    if( libcnotify_verbose != 0 )
1188
    {
1189
      libcnotify_printf(
1190
       "%s: reading volume information at offset: %" PRIi32 " (0x%08" PRIx32 ")\n",
1191
       function,
1192
       volumes_information_offset + volume_information_offset,
1193
       volumes_information_offset + volume_information_offset );
1194
    }
1195
#endif
1196
4.78k
    volume_information_data = &( volumes_information_data[ volume_information_offset ] );
1197
1198
#if defined( HAVE_DEBUG_OUTPUT )
1199
    if( libcnotify_verbose != 0 )
1200
    {
1201
      libcnotify_printf(
1202
       "%s: volume: %d information data:\n",
1203
       function,
1204
       volume_index );
1205
      libcnotify_print_data(
1206
       volume_information_data,
1207
       volume_information_size,
1208
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1209
    }
1210
#endif
1211
4.78k
    byte_stream_copy_to_uint32_little_endian(
1212
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->device_path_offset,
1213
4.78k
     device_path_offset );
1214
1215
4.78k
    byte_stream_copy_to_uint32_little_endian(
1216
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->device_path_number_of_characters,
1217
4.78k
     device_path_size );
1218
1219
4.78k
    byte_stream_copy_to_uint64_little_endian(
1220
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->creation_time,
1221
4.78k
     volume_information->creation_time );
1222
1223
4.78k
    byte_stream_copy_to_uint32_little_endian(
1224
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->serial_number,
1225
4.78k
     volume_information->serial_number );
1226
1227
4.78k
    byte_stream_copy_to_uint32_little_endian(
1228
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->file_references_offset,
1229
4.78k
     file_references_offset );
1230
1231
4.78k
    byte_stream_copy_to_uint32_little_endian(
1232
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->file_references_size,
1233
4.78k
     file_references_size );
1234
1235
4.78k
    byte_stream_copy_to_uint32_little_endian(
1236
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->directory_strings_array_offset,
1237
4.78k
     directory_strings_array_offset );
1238
1239
4.78k
    byte_stream_copy_to_uint32_little_endian(
1240
4.78k
     ( (scca_volume_information_v17_t *) volume_information_data )->number_of_directory_strings,
1241
4.78k
     number_of_directory_strings );
1242
1243
#if defined( HAVE_DEBUG_OUTPUT )
1244
    if( libcnotify_verbose != 0 )
1245
    {
1246
      libcnotify_printf(
1247
       "%s: device path offset\t\t\t: 0x%08" PRIx32 "\n",
1248
       function,
1249
       device_path_offset );
1250
1251
      libcnotify_printf(
1252
       "%s: device path number of characters\t: %" PRIu32 "\n",
1253
       function,
1254
       device_path_size );
1255
1256
      if( libscca_debug_print_filetime_value(
1257
           function,
1258
           "creation time\t\t\t",
1259
           ( (scca_volume_information_v17_t *) volume_information_data )->creation_time,
1260
           8,
1261
           LIBFDATETIME_ENDIAN_LITTLE,
1262
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
1263
           error ) != 1 )
1264
      {
1265
        libcerror_error_set(
1266
         error,
1267
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1268
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1269
         "%s: unable to print filetime value.",
1270
         function );
1271
1272
        goto on_error;
1273
      }
1274
      libcnotify_printf(
1275
       "%s: serial number\t\t\t: 0x%08" PRIx32 "\n",
1276
       function,
1277
       volume_information->serial_number );
1278
1279
      libcnotify_printf(
1280
       "%s: file references offset\t\t: 0x%08" PRIx32 "\n",
1281
       function,
1282
       file_references_offset );
1283
1284
      libcnotify_printf(
1285
       "%s: file references size\t\t: %" PRIu32 "\n",
1286
       function,
1287
       file_references_size );
1288
1289
      libcnotify_printf(
1290
       "%s: directory strings array offset\t: 0x%08" PRIx32 "\n",
1291
       function,
1292
       directory_strings_array_offset );
1293
1294
      libcnotify_printf(
1295
       "%s: number of directory strings\t\t: %" PRIu32 "\n",
1296
       function,
1297
       number_of_directory_strings );
1298
1299
      byte_stream_copy_to_uint32_little_endian(
1300
       ( (scca_volume_information_v17_t *) volume_information_data )->unknown1,
1301
       value_32bit );
1302
      libcnotify_printf(
1303
       "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
1304
       function,
1305
       value_32bit );
1306
1307
      if( ( io_handle->format_version == 23 )
1308
       || ( io_handle->format_version == 26 ) )
1309
      {
1310
        libcnotify_printf(
1311
         "%s: unknown2:\n",
1312
         function );
1313
        libcnotify_print_data(
1314
         ( (scca_volume_information_v23_t *) volume_information_data )->unknown2,
1315
         28,
1316
         0 );
1317
1318
        byte_stream_copy_to_uint32_little_endian(
1319
         ( (scca_volume_information_v23_t *) volume_information_data )->unknown3,
1320
         value_32bit );
1321
        libcnotify_printf(
1322
         "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
1323
         function,
1324
         value_32bit );
1325
1326
        libcnotify_printf(
1327
         "%s: unknown4:\n",
1328
         function );
1329
        libcnotify_print_data(
1330
         ( (scca_volume_information_v23_t *) volume_information_data )->unknown4,
1331
         28,
1332
         0 );
1333
1334
        byte_stream_copy_to_uint32_little_endian(
1335
         ( (scca_volume_information_v23_t *) volume_information_data )->unknown5,
1336
         value_32bit );
1337
        libcnotify_printf(
1338
         "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
1339
         function,
1340
         value_32bit );
1341
      }
1342
      else if( ( io_handle->format_version == 30 )
1343
            || ( io_handle->format_version == 31 ) )
1344
      {
1345
        libcnotify_printf(
1346
         "%s: unknown2:\n",
1347
         function );
1348
        libcnotify_print_data(
1349
         ( (scca_volume_information_v30_t *) volume_information_data )->unknown2,
1350
         24,
1351
         0 );
1352
1353
        byte_stream_copy_to_uint32_little_endian(
1354
         ( (scca_volume_information_v30_t *) volume_information_data )->unknown3,
1355
         value_32bit );
1356
        libcnotify_printf(
1357
         "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
1358
         function,
1359
         value_32bit );
1360
1361
        libcnotify_printf(
1362
         "%s: unknown4:\n",
1363
         function );
1364
        libcnotify_print_data(
1365
         ( (scca_volume_information_v30_t *) volume_information_data )->unknown4,
1366
         24,
1367
         0 );
1368
1369
        byte_stream_copy_to_uint32_little_endian(
1370
         ( (scca_volume_information_v30_t *) volume_information_data )->unknown5,
1371
         value_32bit );
1372
        libcnotify_printf(
1373
         "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
1374
         function,
1375
         value_32bit );
1376
      }
1377
      libcnotify_printf(
1378
       "\n" );
1379
    }
1380
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1381
1382
4.78k
    volume_information_offset += volume_information_size;
1383
1384
4.78k
    if( ( device_path_offset != 0 )
1385
4.78k
     && ( device_path_size > 0 ) )
1386
175
    {
1387
175
      if( ( device_path_offset < volume_information_offset )
1388
175
       || ( device_path_offset >= volumes_information_size ) )
1389
74
      {
1390
74
        libcerror_error_set(
1391
74
         error,
1392
74
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1393
74
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1394
74
         "%s: invalid volume device path offset value out of bounds.",
1395
74
         function );
1396
1397
74
        goto on_error;
1398
74
      }
1399
101
      if( device_path_size > ( volumes_information_size / 2 ) )
1400
42
      {
1401
42
        libcerror_error_set(
1402
42
         error,
1403
42
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1404
42
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1405
42
         "%s: invalid volume device path size value out of bounds.",
1406
42
         function );
1407
1408
42
        goto on_error;
1409
42
      }
1410
59
      device_path_size *= 2;
1411
1412
59
      if( device_path_offset >= ( volumes_information_size - device_path_size ) )
1413
2
      {
1414
2
        libcerror_error_set(
1415
2
         error,
1416
2
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1417
2
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1418
2
         "%s: invalid volume device path size value out of bounds.",
1419
2
         function );
1420
1421
2
        goto on_error;
1422
2
      }
1423
57
      volume_information->device_path = (uint8_t *) memory_allocate(
1424
57
                                                     sizeof( uint8_t ) * device_path_size );
1425
1426
57
      if( volume_information->device_path == NULL )
1427
0
      {
1428
0
        libcerror_error_set(
1429
0
         error,
1430
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1431
0
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1432
0
         "%s: unable to create device path.",
1433
0
         function );
1434
1435
0
        goto on_error;
1436
0
      }
1437
57
      volume_information->device_path_size = device_path_size;
1438
1439
57
      if( memory_copy(
1440
57
           volume_information->device_path,
1441
57
           &( volumes_information_data[ device_path_offset ] ),
1442
57
           device_path_size ) == NULL )
1443
0
      {
1444
0
        libcerror_error_set(
1445
0
         error,
1446
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1447
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1448
0
         "%s: unable to copy device path.",
1449
0
         function );
1450
1451
0
        goto on_error;
1452
0
      }
1453
#if defined( HAVE_DEBUG_OUTPUT )
1454
      if( libcnotify_verbose != 0 )
1455
      {
1456
        if( libscca_debug_print_utf16_string_value(
1457
             function,
1458
             "volume device path\t\t\t",
1459
             volume_information->device_path,
1460
             volume_information->device_path_size,
1461
             LIBUNA_ENDIAN_LITTLE,
1462
             error ) != 1 )
1463
        {
1464
          libcerror_error_set(
1465
           error,
1466
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1467
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1468
           "%s: unable to print UTF-16 string value.",
1469
           function );
1470
1471
          goto on_error;
1472
        }
1473
      }
1474
#endif
1475
57
    }
1476
4.66k
    if( file_references_offset != 0 )
1477
296
    {
1478
296
      if( ( file_references_offset < volume_information_offset )
1479
296
       || ( file_references_offset >= volumes_information_size ) )
1480
68
      {
1481
68
        libcerror_error_set(
1482
68
         error,
1483
68
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1484
68
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1485
68
         "%s: invalid file references offset value out of bounds.",
1486
68
         function );
1487
1488
68
        goto on_error;
1489
68
      }
1490
228
      if( ( file_references_size < 8 )
1491
228
       || ( file_references_size > volumes_information_size )
1492
228
       || ( file_references_offset >= ( volumes_information_size - file_references_size ) ) )
1493
85
      {
1494
85
        libcerror_error_set(
1495
85
         error,
1496
85
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1497
85
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1498
85
         "%s: invalid file references size value out of bounds.",
1499
85
         function );
1500
1501
85
        goto on_error;
1502
85
      }
1503
#if defined( HAVE_DEBUG_OUTPUT )
1504
      if( libcnotify_verbose != 0 )
1505
      {
1506
        libcnotify_printf(
1507
         "%s: file references data:\n",
1508
         function );
1509
        libcnotify_print_data(
1510
         &( volumes_information_data[ file_references_offset ] ),
1511
         file_references_size,
1512
         LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1513
      }
1514
#endif
1515
143
      byte_stream_copy_to_uint32_little_endian(
1516
143
       &( volumes_information_data[ file_references_offset ] ),
1517
143
       version );
1518
1519
143
      file_references_offset += 4;
1520
1521
143
      byte_stream_copy_to_uint32_little_endian(
1522
143
       &( volumes_information_data[ file_references_offset ] ),
1523
143
       number_of_file_references );
1524
1525
143
      file_references_offset += 4;
1526
1527
#if defined( HAVE_DEBUG_OUTPUT )
1528
      if( libcnotify_verbose != 0 )
1529
      {
1530
        libcnotify_printf(
1531
         "%s: version\t\t\t\t: %" PRIu32 "\n",
1532
         function,
1533
         version );
1534
1535
        libcnotify_printf(
1536
         "%s: number of file references\t\t: %" PRIu32 "\n",
1537
         function,
1538
         number_of_file_references );
1539
      }
1540
#endif
1541
143
      if( ( number_of_file_references > ( ( file_references_size - 8 ) / 8 ) )
1542
143
       || ( number_of_file_references > ( volumes_information_size / 8 ) )
1543
143
       || ( file_references_offset >= ( volumes_information_size - ( (size_t) number_of_file_references * 8 ) ) ) )
1544
44
      {
1545
44
        libcerror_error_set(
1546
44
         error,
1547
44
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1548
44
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1549
44
         "%s: invalid number of file references value out of bounds.",
1550
44
         function );
1551
1552
44
        goto on_error;
1553
44
      }
1554
#if defined( HAVE_DEBUG_OUTPUT )
1555
      if( libcnotify_verbose != 0 )
1556
      {
1557
        if( io_handle->format_version >= 23 )
1558
        {
1559
          byte_stream_copy_to_uint64_little_endian(
1560
           &( volumes_information_data[ file_references_offset ] ),
1561
           value_64bit );
1562
          libcnotify_printf(
1563
           "%s: unknown\t\t\t\t: 0x%08" PRIx64 "\n",
1564
           function,
1565
           value_64bit );
1566
1567
          file_references_offset += 8;
1568
        }
1569
        for( file_references_index = 0;
1570
             file_references_index < number_of_file_references;
1571
             file_references_index++ )
1572
        {
1573
          byte_stream_copy_to_uint64_little_endian(
1574
           &( volumes_information_data[ file_references_offset ] ),
1575
           value_64bit );
1576
1577
          if( value_64bit == 0 )
1578
          {
1579
            libcnotify_printf(
1580
             "%s: file reference: %d\t\t\t: %" PRIu64 "\n",
1581
             function,
1582
             file_references_index,
1583
             value_64bit );
1584
          }
1585
          else
1586
          {
1587
            libcnotify_printf(
1588
             "%s: file reference: %d\t\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n",
1589
             function,
1590
             file_references_index,
1591
             value_64bit & 0xffffffffffffUL,
1592
             value_64bit >> 48 );
1593
          }
1594
          file_references_offset += 8;
1595
        }
1596
        libcnotify_printf(
1597
         "\n" );
1598
      }
1599
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1600
143
    }
1601
4.46k
    if( directory_strings_array_offset != 0 )
1602
539
    {
1603
539
      if( ( directory_strings_array_offset < volume_information_offset )
1604
539
       || ( directory_strings_array_offset >= volumes_information_size ) )
1605
114
      {
1606
114
        libcerror_error_set(
1607
114
         error,
1608
114
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1609
114
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1610
114
         "%s: invalid directory strings array offset value out of bounds.",
1611
114
         function );
1612
1613
114
        goto on_error;
1614
114
      }
1615
425
      if( number_of_directory_strings > ( ( volumes_information_size - directory_strings_array_offset ) / 4 ) )
1616
46
      {
1617
46
        libcerror_error_set(
1618
46
         error,
1619
46
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1620
46
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1621
46
         "%s: invalid number of directory strings value out of bounds.",
1622
46
         function );
1623
1624
46
        goto on_error;
1625
46
      }
1626
379
      if( libfvalue_value_type_initialize(
1627
379
           &( volume_information->directory_strings ),
1628
379
           LIBFVALUE_VALUE_TYPE_STRING_UTF16,
1629
379
           error ) != 1 )
1630
0
      {
1631
0
        libcerror_error_set(
1632
0
         error,
1633
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1634
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1635
0
         "%s: unable to create directory strings value.",
1636
0
         function );
1637
1638
0
        goto on_error;
1639
0
      }
1640
379
      directory_string_index  = 0;
1641
379
      directory_string_offset = directory_strings_array_offset;
1642
1643
186k
      while( directory_string_offset < ( volumes_information_size - 4 ) )
1644
186k
      {
1645
186k
        if( ( number_of_directory_strings == 0 )
1646
186k
         || ( directory_string_index >= ( number_of_directory_strings - 1 ) ) )
1647
221
        {
1648
221
          break;
1649
221
        }
1650
186k
        byte_stream_copy_to_uint16_little_endian(
1651
186k
         &( volumes_information_data[ directory_string_offset ] ),
1652
186k
         number_of_characters );
1653
1654
#if defined( HAVE_DEBUG_OUTPUT )
1655
        if( libcnotify_verbose != 0 )
1656
        {
1657
          libcnotify_printf(
1658
           "%s: directory string: %" PRIu32 " data offset\t\t: 0x%08" PRIzx "\n",
1659
           function,
1660
           directory_string_index,
1661
           directory_string_offset );
1662
1663
          libcnotify_printf(
1664
           "%s: directory string: %" PRIu32 " number of characters\t: %" PRIu16 " (%" PRIu32 ")\n",
1665
           function,
1666
           directory_string_index,
1667
           number_of_characters,
1668
           ( (uint32_t) number_of_characters * 2 ) + 2 );
1669
        }
1670
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1671
1672
186k
        directory_string_offset += 2;
1673
1674
186k
        if( number_of_characters > ( ( volumes_information_size - 2 - directory_string_offset ) / 2 ) )
1675
57
        {
1676
57
          libcerror_error_set(
1677
57
           error,
1678
57
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1679
57
           LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1680
57
           "%s: invalid directory string: %" PRIu32 " number of characters value out of bounds.",
1681
57
           function,
1682
57
           directory_string_index );
1683
1684
57
          goto on_error;
1685
57
        }
1686
        /* The number of characters does not include the end-of-string character
1687
         */
1688
185k
        directory_string_size = ( number_of_characters * 2 ) + 2;
1689
1690
#if defined( HAVE_DEBUG_OUTPUT )
1691
        if( libcnotify_verbose != 0 )
1692
        {
1693
          libcnotify_printf(
1694
           "%s: directory string: %" PRIu32 " data:\n",
1695
           function,
1696
           directory_string_index );
1697
          libcnotify_print_data(
1698
           &( volumes_information_data[ directory_string_offset ] ),
1699
           (size_t) directory_string_size,
1700
           LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
1701
        }
1702
#endif
1703
#ifdef TODO
1704
/* TODO disabled for now, is causing delays with the OSSFuzz tests */
1705
1706
        if( libfvalue_value_append_entry_data(
1707
             volume_information->directory_strings,
1708
             &entry_index,
1709
             &( volumes_information_data[ directory_string_offset ] ),
1710
             (size_t) directory_string_size,
1711
             LIBFVALUE_CODEPAGE_UTF16_LITTLE_ENDIAN,
1712
             error ) != 1 )
1713
        {
1714
          libcerror_error_set(
1715
           error,
1716
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
1717
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1718
           "%s: unable to append directory string.",
1719
           function );
1720
1721
          goto on_error;
1722
        }
1723
#endif /* TODO */
1724
185k
        directory_string_offset += directory_string_size;
1725
1726
185k
        directory_string_index++;
1727
185k
      }
1728
379
    }
1729
4.24k
    if( libcdata_array_append_entry(
1730
4.24k
         volumes_array,
1731
4.24k
         &entry_index,
1732
4.24k
         (intptr_t *) volume_information,
1733
4.24k
         error ) != 1 )
1734
0
    {
1735
0
      libcerror_error_set(
1736
0
       error,
1737
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1738
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
1739
0
       "%s: unable to append volume: %" PRIu32 " information to array.",
1740
0
       function,
1741
0
       volume_index );
1742
1743
0
      goto on_error;
1744
0
    }
1745
4.24k
    volume_information = NULL;
1746
4.24k
  }
1747
4
  memory_free(
1748
4
   volumes_information_data );
1749
1750
4
  return( 1 );
1751
1752
661
on_error:
1753
661
  if( volume_information != NULL )
1754
583
  {
1755
583
    libscca_internal_volume_information_free(
1756
583
     &volume_information,
1757
583
     NULL );
1758
583
  }
1759
661
  if( volumes_information_data != NULL )
1760
637
  {
1761
637
    memory_free(
1762
637
     volumes_information_data );
1763
637
  }
1764
661
  return( -1 );
1765
587
}
1766
1767
/* Reads data from the current offset into a buffer
1768
 * Callback for the uncompressed block stream
1769
 * Returns the number of bytes read or -1 on error
1770
 */
1771
ssize_t libscca_io_handle_read_segment_data(
1772
         intptr_t *data_handle LIBSCCA_ATTRIBUTE_UNUSED,
1773
         intptr_t *file_io_handle,
1774
         int segment_index,
1775
         int segment_file_index LIBSCCA_ATTRIBUTE_UNUSED,
1776
         uint8_t *segment_data,
1777
         size_t segment_data_size,
1778
         uint32_t segment_flags LIBSCCA_ATTRIBUTE_UNUSED,
1779
         uint8_t read_flags LIBSCCA_ATTRIBUTE_UNUSED,
1780
         libcerror_error_t **error )
1781
3.90k
{
1782
3.90k
  static char *function = "libscca_io_handle_read_segment_data";
1783
3.90k
  ssize_t read_count    = 0;
1784
1785
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( data_handle )
1786
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( segment_file_index )
1787
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( segment_flags )
1788
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( read_flags )
1789
1790
3.90k
  if( segment_data_size > (size64_t) SSIZE_MAX )
1791
0
  {
1792
0
    libcerror_error_set(
1793
0
     error,
1794
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1795
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1796
0
     "%s: invalid segment data size value out of bounds.",
1797
0
     function );
1798
1799
0
    return( -1 );
1800
0
  }
1801
3.90k
  read_count = libbfio_handle_read_buffer(
1802
3.90k
                (libbfio_handle_t *) file_io_handle,
1803
3.90k
                segment_data,
1804
3.90k
                segment_data_size,
1805
3.90k
                error );
1806
1807
3.90k
  if( read_count != (ssize_t) segment_data_size )
1808
0
  {
1809
0
    libcerror_error_set(
1810
0
     error,
1811
0
     LIBCERROR_ERROR_DOMAIN_IO,
1812
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1813
0
     "%s: unable to read segment: %d data.",
1814
0
     function,
1815
0
     segment_index );
1816
1817
0
    return( -1 );
1818
0
  }
1819
3.90k
  return( read_count );
1820
3.90k
}
1821
1822
/* Seeks a certain offset of the data
1823
 * Callback for the uncompressed block stream
1824
 * Returns the offset if seek is successful or -1 on error
1825
 */
1826
off64_t libscca_io_handle_seek_segment_offset(
1827
         intptr_t *data_handle LIBSCCA_ATTRIBUTE_UNUSED,
1828
         intptr_t *file_io_handle,
1829
         int segment_index,
1830
         int segment_file_index LIBSCCA_ATTRIBUTE_UNUSED,
1831
         off64_t segment_offset,
1832
         libcerror_error_t **error )
1833
3.90k
{
1834
3.90k
  static char *function = "libscca_io_handle_seek_segment_offset";
1835
1836
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( data_handle )
1837
3.90k
  LIBSCCA_UNREFERENCED_PARAMETER( segment_file_index )
1838
1839
3.90k
  if( libbfio_handle_seek_offset(
1840
3.90k
       (libbfio_handle_t *) file_io_handle,
1841
3.90k
       segment_offset,
1842
3.90k
       SEEK_SET,
1843
3.90k
       error ) == -1 )
1844
0
  {
1845
0
    libcerror_error_set(
1846
0
     error,
1847
0
     LIBCERROR_ERROR_DOMAIN_IO,
1848
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
1849
0
     "%s: unable to seek segment: %d offset: %" PRIi64 ".",
1850
0
     function,
1851
0
     segment_index,
1852
0
     segment_offset );
1853
1854
0
    return( -1 );
1855
0
  }
1856
3.90k
  return( segment_offset );
1857
3.90k
}
1858