Coverage Report

Created: 2025-06-22 07:35

/src/libagdb/libagdb/libagdb_io_handle.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Input/Output (IO) handle functions
3
 *
4
 * Copyright (C) 2014-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 "libagdb_debug.h"
28
#include "libagdb_definitions.h"
29
#include "libagdb_io_handle.h"
30
#include "libagdb_libbfio.h"
31
#include "libagdb_libcerror.h"
32
#include "libagdb_libcnotify.h"
33
#include "libagdb_libfcache.h"
34
#include "libagdb_libfdata.h"
35
#include "libagdb_unused.h"
36
37
#include "agdb_file_header.h"
38
39
const char *agdb_mem_file_signature_vista = "MEMO";
40
const char *agdb_mem_file_signature_win7  = "MEM0";
41
const char *agdb_mam_file_signature_win8  = "MAM\x84";
42
43
/* Creates an IO handle
44
 * Make sure the value io_handle is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libagdb_io_handle_initialize(
48
     libagdb_io_handle_t **io_handle,
49
     libcerror_error_t **error )
50
2.28k
{
51
2.28k
  static char *function = "libagdb_io_handle_initialize";
52
53
2.28k
  if( io_handle == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid IO handle.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
2.28k
  if( *io_handle != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid IO handle value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
2.28k
  *io_handle = memory_allocate_structure(
76
2.28k
                libagdb_io_handle_t );
77
78
2.28k
  if( *io_handle == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create IO handle.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
2.28k
  if( memory_set(
90
2.28k
       *io_handle,
91
2.28k
       0,
92
2.28k
       sizeof( libagdb_io_handle_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear file.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
2.28k
  return( 1 );
104
105
0
on_error:
106
0
  if( *io_handle != NULL )
107
0
  {
108
0
    memory_free(
109
0
     *io_handle );
110
111
0
    *io_handle = NULL;
112
0
  }
113
0
  return( -1 );
114
2.28k
}
115
116
/* Frees a IO handle
117
 * Returns 1 if successful or -1 on error
118
 */
119
int libagdb_io_handle_free(
120
     libagdb_io_handle_t **io_handle,
121
     libcerror_error_t **error )
122
2.28k
{
123
2.28k
  static char *function = "libagdb_io_handle_free";
124
125
2.28k
  if( io_handle == NULL )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
130
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
131
0
     "%s: invalid IO handle.",
132
0
     function );
133
134
0
    return( -1 );
135
0
  }
136
2.28k
  if( *io_handle != NULL )
137
2.28k
  {
138
2.28k
    memory_free(
139
2.28k
     *io_handle );
140
141
2.28k
    *io_handle = NULL;
142
2.28k
  }
143
2.28k
  return( 1 );
144
2.28k
}
145
146
/* Clears the IO handle
147
 * Returns 1 if successful or -1 on error
148
 */
149
int libagdb_io_handle_clear(
150
     libagdb_io_handle_t *io_handle,
151
     libcerror_error_t **error )
152
24
{
153
24
  static char *function = "libagdb_io_handle_clear";
154
155
24
  if( io_handle == 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 IO handle.",
162
0
     function );
163
164
0
    return( -1 );
165
0
  }
166
24
  if( memory_set(
167
24
       io_handle,
168
24
       0,
169
24
       sizeof( libagdb_io_handle_t ) ) == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
174
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
175
0
     "%s: unable to clear IO handle.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
24
  return( 1 );
181
24
}
182
183
/* Reads the compressed blocks
184
 * Returns 1 if successful or -1 on error
185
 */
186
int libagdb_io_handle_read_compressed_blocks(
187
     libagdb_io_handle_t *io_handle,
188
     libbfio_handle_t *file_io_handle,
189
     libfdata_list_t *compressed_blocks_list,
190
     libcerror_error_t **error )
191
2.02k
{
192
2.02k
  uint8_t compressed_block_data[ 4 ];
193
194
2.02k
  static char *function            = "libagdb_io_handle_read_compressed_blocks";
195
2.02k
  off64_t file_offset              = 0;
196
2.02k
  size_t read_size                 = 0;
197
2.02k
  ssize_t read_count               = 0;
198
2.02k
  uint32_t compressed_block_size   = 0;
199
2.02k
  uint32_t uncompressed_data_size  = 0;
200
2.02k
  uint32_t uncompressed_block_size = 0;
201
2.02k
  int compressed_block_index       = 0;
202
2.02k
  int element_index                = 0;
203
204
2.02k
  if( io_handle == NULL )
205
0
  {
206
0
    libcerror_error_set(
207
0
     error,
208
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
209
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
210
0
     "%s: invalid IO handle.",
211
0
     function );
212
213
0
    return( -1 );
214
0
  }
215
2.02k
  if( ( io_handle->file_type != LIBAGDB_FILE_TYPE_COMPRESSED_VISTA )
216
2.02k
   && ( io_handle->file_type != LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS7 )
217
2.02k
   && ( io_handle->file_type != LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS8 ) )
218
0
  {
219
0
    libcerror_error_set(
220
0
     error,
221
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
222
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
223
0
     "%s: invalid IO handle - unsupported file type.",
224
0
     function );
225
226
0
    return( -1 );
227
0
  }
228
2.02k
  if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_VISTA )
229
1.57k
  {
230
1.57k
    file_offset = 8;
231
1.57k
    read_size   = 2;
232
1.57k
  }
233
456
  else if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS7 )
234
453
  {
235
453
    file_offset = 8;
236
453
    read_size   = 4;
237
453
  }
238
3
  else if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS8 )
239
3
  {
240
/* TODO implement */
241
3
    file_offset = 4;
242
3
    read_size   = 4;
243
3
  }
244
2.02k
  uncompressed_data_size = io_handle->uncompressed_data_size;
245
246
1.54M
  while( (size64_t) file_offset < io_handle->file_size )
247
1.54M
  {
248
#if defined( HAVE_DEBUG_OUTPUT )
249
    if( libcnotify_verbose != 0 )
250
    {
251
      libcnotify_printf(
252
       "%s: reading compressed data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
253
       function,
254
       file_offset,
255
       file_offset );
256
    }
257
#endif
258
1.54M
    read_count = libbfio_handle_read_buffer_at_offset(
259
1.54M
                  file_io_handle,
260
1.54M
                  compressed_block_data,
261
1.54M
                  read_size,
262
1.54M
                  file_offset,
263
1.54M
                  error );
264
265
1.54M
    if( read_count != (ssize_t) read_size )
266
30
    {
267
30
      libcerror_error_set(
268
30
       error,
269
30
       LIBCERROR_ERROR_DOMAIN_IO,
270
30
       LIBCERROR_IO_ERROR_READ_FAILED,
271
30
       "%s: unable to read compressed block data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
272
30
       function,
273
30
       file_offset,
274
30
       file_offset );
275
276
30
      return( -1 );
277
30
    }
278
1.54M
    if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_VISTA )
279
1.49M
    {
280
1.49M
      byte_stream_copy_to_uint16_little_endian(
281
1.49M
       compressed_block_data,
282
1.49M
       compressed_block_size );
283
284
1.49M
      compressed_block_size &= 0x0fff;
285
286
1.49M
      if( compressed_block_size == 0 )
287
9
      {
288
9
        libcerror_error_set(
289
9
         error,
290
9
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
291
9
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
292
9
         "%s: invalid compressed block size value out of bounds.",
293
9
         function );
294
295
9
        return( -1 );
296
9
      }
297
1.49M
      compressed_block_size += 3;
298
1.49M
    }
299
54.0k
    else if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS7 )
300
54.0k
    {
301
54.0k
      byte_stream_copy_to_uint32_little_endian(
302
54.0k
       compressed_block_data,
303
54.0k
       compressed_block_size );
304
305
54.0k
      file_offset += 4;
306
54.0k
    }
307
3
    else if( io_handle->file_type == LIBAGDB_FILE_TYPE_COMPRESSED_WINDOWS8 )
308
3
    {
309
/* TODO implement read the block and determine the range */
310
3
    }
311
1.54M
    if( uncompressed_data_size < io_handle->uncompressed_block_size )
312
356
    {
313
356
      uncompressed_block_size = uncompressed_data_size;
314
356
    }
315
1.54M
    else
316
1.54M
    {
317
1.54M
      uncompressed_block_size = io_handle->uncompressed_block_size;
318
1.54M
    }
319
#if defined( HAVE_DEBUG_OUTPUT )
320
    if( libcnotify_verbose != 0 )
321
    {
322
      libcnotify_printf(
323
       "%s: compressed block: %d size\t: %" PRIu32 "\n",
324
       function,
325
       compressed_block_index,
326
       compressed_block_size );
327
    }
328
#endif
329
1.54M
    if( compressed_block_size == 0 )
330
5
    {
331
5
      libcerror_error_set(
332
5
       error,
333
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
334
5
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
335
5
       "%s: invalid compressed block size value out of bounds.",
336
5
       function );
337
338
5
      return( -1 );
339
5
    }
340
1.54M
    if( libfdata_list_append_element_with_mapped_size(
341
1.54M
         compressed_blocks_list,
342
1.54M
         &element_index,
343
1.54M
         0,
344
1.54M
         file_offset,
345
1.54M
         (size64_t) compressed_block_size,
346
1.54M
         LIBFDATA_RANGE_FLAG_IS_COMPRESSED,
347
1.54M
         uncompressed_block_size,
348
1.54M
         error ) != 1 )
349
0
    {
350
0
      libcerror_error_set(
351
0
       error,
352
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
353
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
354
0
       "%s: unable to append compressed block: %d to list.",
355
0
       function,
356
0
       compressed_block_index );
357
358
0
      return( -1 );
359
0
    }
360
1.54M
    file_offset            += compressed_block_size;
361
1.54M
    uncompressed_data_size -= uncompressed_block_size;
362
363
1.54M
    if( uncompressed_data_size == 0 )
364
354
    {
365
354
      break;
366
354
    }
367
1.54M
    compressed_block_index++;
368
1.54M
  }
369
#if defined( HAVE_DEBUG_OUTPUT )
370
  if( libcnotify_verbose != 0 )
371
  {
372
    if( (size64_t) file_offset < io_handle->file_size )
373
    {
374
      libcnotify_printf(
375
       "%s: trailing data size\t: %" PRIu64 "\n",
376
       function,
377
       io_handle->file_size - (size64_t) file_offset );
378
    }
379
  }
380
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
381
382
1.98k
  return( 1 );
383
2.02k
}
384
385
/* Reads the uncompressed file header
386
 * Returns 1 if successful or -1 on error
387
 */
388
int libagdb_io_handle_read_uncompressed_file_header(
389
     libagdb_io_handle_t *io_handle,
390
     libfdata_stream_t *uncompressed_data_stream,
391
     libbfio_handle_t *file_io_handle,
392
     off64_t *volumes_information_offset,
393
     uint32_t *number_of_volumes,
394
     uint32_t *number_of_sources,
395
     libcerror_error_t **error )
396
2.14k
{
397
2.14k
  agdb_file_header_t file_header_data;
398
399
2.14k
  uint8_t *database_header_data = NULL;
400
2.14k
  static char *function         = "libagdb_io_handle_read_uncompressed_file_header";
401
2.14k
  size64_t data_stream_size     = 0;
402
2.14k
  size_t database_header_size   = 0;
403
2.14k
  ssize_t read_count            = 0;
404
2.14k
  uint32_t data_size            = 0;
405
2.14k
  uint32_t header_size          = 0;
406
2.14k
  uint32_t unknown1             = 0;
407
408
#if defined( HAVE_DEBUG_OUTPUT )
409
  uint32_t value_32bit          = 0;
410
#endif
411
412
2.14k
  if( io_handle == NULL )
413
0
  {
414
0
    libcerror_error_set(
415
0
     error,
416
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
417
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
418
0
     "%s: invalid IO handle.",
419
0
     function );
420
421
0
    return( -1 );
422
0
  }
423
2.14k
  if( volumes_information_offset == NULL )
424
0
  {
425
0
    libcerror_error_set(
426
0
     error,
427
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
428
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
429
0
     "%s: invalid volumes information offset.",
430
0
     function );
431
432
0
    return( -1 );
433
0
  }
434
2.14k
  if( number_of_volumes == NULL )
435
0
  {
436
0
    libcerror_error_set(
437
0
     error,
438
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
439
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
440
0
     "%s: invalid number of volumes.",
441
0
     function );
442
443
0
    return( -1 );
444
0
  }
445
2.14k
  if( number_of_sources == NULL )
446
0
  {
447
0
    libcerror_error_set(
448
0
     error,
449
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
450
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
451
0
     "%s: invalid number of sources.",
452
0
     function );
453
454
0
    return( -1 );
455
0
  }
456
2.14k
  if( libfdata_stream_get_size(
457
2.14k
       uncompressed_data_stream,
458
2.14k
       &data_stream_size,
459
2.14k
       error ) != 1 )
460
0
  {
461
0
    libcerror_error_set(
462
0
     error,
463
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
464
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
465
0
     "%s: unable to retrieve uncompressed data stream size.",
466
0
     function );
467
468
0
    goto on_error;
469
0
  }
470
#if defined( HAVE_DEBUG_OUTPUT )
471
  if( libcnotify_verbose != 0 )
472
  {
473
    libcnotify_printf(
474
     "%s: reading uncompressed file header at offset: 0 (0x00000000)\n",
475
     function );
476
  }
477
#endif
478
2.14k
  read_count = libfdata_stream_read_buffer_at_offset(
479
2.14k
                uncompressed_data_stream,
480
2.14k
                (intptr_t *) file_io_handle,
481
2.14k
                (uint8_t *) &file_header_data,
482
2.14k
                sizeof( agdb_file_header_t ),
483
2.14k
                0,
484
2.14k
                0,
485
2.14k
                error );
486
487
2.14k
  if( read_count != (ssize_t) sizeof( agdb_file_header_t ) )
488
541
  {
489
541
    libcerror_error_set(
490
541
     error,
491
541
     LIBCERROR_ERROR_DOMAIN_IO,
492
541
     LIBCERROR_IO_ERROR_READ_FAILED,
493
541
     "%s: unable to read file header data offset: %" PRIi64 " (0x%08" PRIx64 ").",
494
541
     function );
495
496
541
    goto on_error;
497
541
  }
498
#if defined( HAVE_DEBUG_OUTPUT )
499
  if( libcnotify_verbose != 0 )
500
  {
501
    libcnotify_printf(
502
     "%s: file header data:\n",
503
     function );
504
    libcnotify_print_data(
505
     (uint8_t *) &file_header_data,
506
     sizeof( agdb_file_header_t ),
507
     0 );
508
  }
509
#endif
510
1.60k
  byte_stream_copy_to_uint32_little_endian(
511
1.60k
   file_header_data.data_size,
512
1.60k
   data_size );
513
514
/* TODO improve detection */
515
1.60k
  if( data_stream_size != (size64_t) data_size )
516
167
  {
517
167
    libcerror_error_set(
518
167
     error,
519
167
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
167
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
521
167
     "%s: invalid data size.",
522
167
     function );
523
524
167
    goto on_error;
525
167
  }
526
1.43k
  byte_stream_copy_to_uint32_little_endian(
527
1.43k
   file_header_data.unknown1,
528
1.43k
   unknown1 );
529
530
1.43k
  if( unknown1 != 0x0000000eUL )
531
8
  {
532
/* TODO add support for AgAppLaunch.db unknown1: 5 */
533
8
    return( 1 );
534
8
  }
535
1.42k
  byte_stream_copy_to_uint32_little_endian(
536
1.42k
   file_header_data.header_size,
537
1.42k
   header_size );
538
539
#if defined( HAVE_DEBUG_OUTPUT )
540
  if( libcnotify_verbose != 0 )
541
  {
542
    libcnotify_printf(
543
     "%s: unknown1\t\t: %" PRIu32 "\n",
544
     function,
545
     unknown1 );
546
547
    libcnotify_printf(
548
     "%s: data size\t\t: %" PRIu32 "\n",
549
     function,
550
     data_size );
551
552
    libcnotify_printf(
553
     "%s: header size\t\t: %" PRIi64 "\n",
554
     function,
555
     header_size );
556
557
    libcnotify_printf(
558
     "\n" );
559
  }
560
#endif
561
1.42k
  if( (size_t) header_size < sizeof( agdb_file_header_t ) )
562
4
  {
563
4
    libcerror_error_set(
564
4
     error,
565
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
566
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
567
4
     "%s: invalid header size value out of bounds.",
568
4
     function );
569
570
4
    goto on_error;
571
4
  }
572
1.42k
  database_header_size = (size_t) header_size - sizeof( agdb_file_header_t );
573
574
1.42k
  if( ( database_header_size < 60 )
575
1.42k
   || ( database_header_size > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
576
17
  {
577
17
    libcerror_error_set(
578
17
     error,
579
17
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
580
17
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
581
17
     "%s: invalid database header size value out of bounds.",
582
17
     function );
583
584
17
    goto on_error;
585
17
  }
586
1.40k
  database_header_data = (uint8_t *) memory_allocate(
587
1.40k
                                      sizeof( uint8_t ) * database_header_size );
588
589
1.40k
  if( database_header_data == NULL )
590
0
  {
591
0
    libcerror_error_set(
592
0
     error,
593
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
594
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
595
0
     "%s: unable to create database header data.",
596
0
     function );
597
598
0
    goto on_error;
599
0
  }
600
1.40k
  read_count = libfdata_stream_read_buffer(
601
1.40k
                uncompressed_data_stream,
602
1.40k
                (intptr_t *) file_io_handle,
603
1.40k
                database_header_data,
604
1.40k
                database_header_size,
605
1.40k
                0,
606
1.40k
                error );
607
608
1.40k
  if( read_count != (ssize_t) database_header_size )
609
119
  {
610
119
    libcerror_error_set(
611
119
     error,
612
119
     LIBCERROR_ERROR_DOMAIN_IO,
613
119
     LIBCERROR_IO_ERROR_READ_FAILED,
614
119
     "%s: unable to read database header data.",
615
119
     function );
616
617
119
    goto on_error;
618
119
  }
619
#if defined( HAVE_DEBUG_OUTPUT )
620
  if( libcnotify_verbose != 0 )
621
  {
622
    libcnotify_printf(
623
     "%s: database header data:\n",
624
     function );
625
    libcnotify_print_data(
626
           database_header_data,
627
           database_header_size,
628
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
629
  }
630
#endif
631
1.28k
  byte_stream_copy_to_uint32_little_endian(
632
1.28k
   ( (agdb_database_header_t *) database_header_data )->database_type,
633
1.28k
   io_handle->database_type );
634
635
1.28k
  byte_stream_copy_to_uint32_little_endian(
636
1.28k
   &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 0 ] ),
637
1.28k
   io_handle->volume_information_entry_size );
638
639
1.28k
  byte_stream_copy_to_uint32_little_endian(
640
1.28k
   &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 4 ] ),
641
1.28k
   io_handle->file_information_entry_size );
642
643
1.28k
  byte_stream_copy_to_uint32_little_endian(
644
1.28k
   &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 8 ] ),
645
1.28k
   io_handle->source_information_entry_size );
646
647
1.28k
  byte_stream_copy_to_uint32_little_endian(
648
1.28k
   &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 12 ] ),
649
1.28k
   io_handle->file_information_sub_entry_type1_size );
650
651
1.28k
  byte_stream_copy_to_uint32_little_endian(
652
1.28k
   &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 16 ] ),
653
1.28k
   io_handle->file_information_sub_entry_type2_size );
654
655
1.28k
  byte_stream_copy_to_uint32_little_endian(
656
1.28k
   ( (agdb_database_header_t *) database_header_data )->number_of_volumes,
657
1.28k
   *number_of_volumes );
658
659
1.28k
  byte_stream_copy_to_uint32_little_endian(
660
1.28k
   ( (agdb_database_header_t *) database_header_data )->number_of_sources,
661
1.28k
   *number_of_sources );
662
663
#if defined( HAVE_DEBUG_OUTPUT )
664
  if( libcnotify_verbose != 0 )
665
  {
666
    libcnotify_printf(
667
     "%s: database type\t\t: %" PRIu32 "\n",
668
     function,
669
     io_handle->database_type );
670
671
    libcnotify_printf(
672
     "%s: database parameters\t: ",
673
     function );
674
675
    byte_stream_copy_to_uint32_little_endian(
676
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 0 ] ),
677
     value_32bit );
678
    libcnotify_printf(
679
     "%" PRIu32 ", ",
680
     value_32bit );
681
682
    byte_stream_copy_to_uint32_little_endian(
683
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 4 ] ),
684
     value_32bit );
685
    libcnotify_printf(
686
     "%" PRIu32 ", ",
687
     value_32bit );
688
689
    byte_stream_copy_to_uint32_little_endian(
690
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 8 ] ),
691
     value_32bit );
692
    libcnotify_printf(
693
     "%" PRIu32 ", ",
694
     value_32bit );
695
696
    byte_stream_copy_to_uint32_little_endian(
697
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 12 ] ),
698
     value_32bit );
699
    libcnotify_printf(
700
     "%" PRIu32 ", ",
701
     value_32bit );
702
703
    byte_stream_copy_to_uint32_little_endian(
704
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 16 ] ),
705
     value_32bit );
706
    libcnotify_printf(
707
     "%" PRIu32 ", ",
708
     value_32bit );
709
710
    byte_stream_copy_to_uint32_little_endian(
711
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 20 ] ),
712
     value_32bit );
713
    libcnotify_printf(
714
     "%" PRIu32 ", ",
715
     value_32bit );
716
717
    byte_stream_copy_to_uint32_little_endian(
718
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 24 ] ),
719
     value_32bit );
720
    libcnotify_printf(
721
     "%" PRIu32 ", ",
722
     value_32bit );
723
724
    byte_stream_copy_to_uint32_little_endian(
725
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 28 ] ),
726
     value_32bit );
727
    libcnotify_printf(
728
     "%" PRIu32 ", ",
729
     value_32bit );
730
731
    byte_stream_copy_to_uint32_little_endian(
732
     &( ( (agdb_database_header_t *) database_header_data )->database_parameters[ 32 ] ),
733
     value_32bit );
734
    libcnotify_printf(
735
     "%" PRIu32 "\n",
736
     value_32bit );
737
738
    libcnotify_printf(
739
     "%s: number of volumes\t: %" PRIu32 "\n",
740
     function,
741
     *number_of_volumes );
742
743
    byte_stream_copy_to_uint32_little_endian(
744
     ( (agdb_database_header_t *) database_header_data )->number_of_files,
745
     value_32bit );
746
    libcnotify_printf(
747
     "%s: number of files\t: %" PRIu32 "\n",
748
     function,
749
     value_32bit );
750
751
    byte_stream_copy_to_uint32_little_endian(
752
     ( (agdb_database_header_t *) database_header_data )->unknown3,
753
     value_32bit );
754
    libcnotify_printf(
755
     "%s: unknown3\t\t: 0x%08" PRIx32 "\n",
756
     function,
757
     value_32bit );
758
759
    libcnotify_printf(
760
     "%s: number of sources\t: %" PRIu32 "\n",
761
     function,
762
     *number_of_sources );
763
764
    byte_stream_copy_to_uint32_little_endian(
765
     ( (agdb_database_header_t *) database_header_data )->unknown4,
766
     value_32bit );
767
    libcnotify_printf(
768
     "%s: unknown4\t\t: 0x%08" PRIx32 "\n",
769
     function,
770
     value_32bit );
771
772
    byte_stream_copy_to_uint32_little_endian(
773
     ( (agdb_database_header_t *) database_header_data )->unknown5,
774
     value_32bit );
775
    libcnotify_printf(
776
     "%s: unknown5\t\t: 0x%08" PRIx32 "\n",
777
     function,
778
     value_32bit );
779
780
    if( ( database_header_size == 116 )
781
     || ( database_header_size == 228 ) )
782
    {
783
      byte_stream_copy_to_uint32_little_endian(
784
       ( (agdb_database_header_116_t *) database_header_data )->unknown6,
785
       value_32bit );
786
      libcnotify_printf(
787
       "%s: unknown6\t\t: 0x%08" PRIx32 "\n",
788
       function,
789
       value_32bit );
790
791
      byte_stream_copy_to_uint32_little_endian(
792
       ( (agdb_database_header_116_t *) database_header_data )->unknown7,
793
       value_32bit );
794
      libcnotify_printf(
795
       "%s: unknown7\t\t: 0x%08" PRIx32 "\n",
796
       function,
797
       value_32bit );
798
799
      byte_stream_copy_to_uint32_little_endian(
800
       ( (agdb_database_header_116_t *) database_header_data )->unknown8,
801
       value_32bit );
802
      libcnotify_printf(
803
       "%s: unknown8\t\t: 0x%08" PRIx32 "\n",
804
       function,
805
       value_32bit );
806
807
      byte_stream_copy_to_uint32_little_endian(
808
       ( (agdb_database_header_116_t *) database_header_data )->unknown9,
809
       value_32bit );
810
      libcnotify_printf(
811
       "%s: unknown9\t\t: 0x%08" PRIx32 "\n",
812
       function,
813
       value_32bit );
814
815
      byte_stream_copy_to_uint32_little_endian(
816
       ( (agdb_database_header_116_t *) database_header_data )->unknown10,
817
       value_32bit );
818
      libcnotify_printf(
819
       "%s: unknown10\t\t: 0x%08" PRIx32 "\n",
820
       function,
821
       value_32bit );
822
823
      byte_stream_copy_to_uint32_little_endian(
824
       ( (agdb_database_header_116_t *) database_header_data )->unknown11,
825
       value_32bit );
826
      libcnotify_printf(
827
       "%s: unknown11\t\t: 0x%08" PRIx32 "\n",
828
       function,
829
       value_32bit );
830
831
      byte_stream_copy_to_uint32_little_endian(
832
       ( (agdb_database_header_116_t *) database_header_data )->unknown12,
833
       value_32bit );
834
      libcnotify_printf(
835
       "%s: unknown12\t\t: 0x%08" PRIx32 "\n",
836
       function,
837
       value_32bit );
838
839
      byte_stream_copy_to_uint32_little_endian(
840
       ( (agdb_database_header_116_t *) database_header_data )->unknown13,
841
       value_32bit );
842
      libcnotify_printf(
843
       "%s: unknown13\t\t: 0x%08" PRIx32 "\n",
844
       function,
845
       value_32bit );
846
847
      byte_stream_copy_to_uint32_little_endian(
848
       ( (agdb_database_header_116_t *) database_header_data )->unknown14,
849
       value_32bit );
850
      libcnotify_printf(
851
       "%s: unknown14\t\t: 0x%08" PRIx32 "\n",
852
       function,
853
       value_32bit );
854
855
      byte_stream_copy_to_uint32_little_endian(
856
       ( (agdb_database_header_116_t *) database_header_data )->unknown15,
857
       value_32bit );
858
      libcnotify_printf(
859
       "%s: unknown15\t\t: 0x%08" PRIx32 "\n",
860
       function,
861
       value_32bit );
862
    }
863
    if( database_header_size == 116 )
864
    {
865
      byte_stream_copy_to_uint32_little_endian(
866
       ( (agdb_database_header_116_t *) database_header_data )->unknown16,
867
       value_32bit );
868
      libcnotify_printf(
869
       "%s: unknown16\t\t: 0x%08" PRIx32 "\n",
870
       function,
871
       value_32bit );
872
873
      byte_stream_copy_to_uint32_little_endian(
874
       ( (agdb_database_header_116_t *) database_header_data )->unknown17,
875
       value_32bit );
876
      libcnotify_printf(
877
       "%s: unknown17\t\t: 0x%08" PRIx32 "\n",
878
       function,
879
       value_32bit );
880
881
      byte_stream_copy_to_uint32_little_endian(
882
       ( (agdb_database_header_116_t *) database_header_data )->unknown18,
883
       value_32bit );
884
      libcnotify_printf(
885
       "%s: unknown18\t\t: 0x%08" PRIx32 "\n",
886
       function,
887
       value_32bit );
888
    }
889
    else if( database_header_size == 228 )
890
    {
891
      byte_stream_copy_to_uint32_little_endian(
892
       ( (agdb_database_header_116_t *) database_header_data )->unknown16,
893
       value_32bit );
894
      libcnotify_printf(
895
       "%s: number of time values\t: %" PRIu32 "\n",
896
       function,
897
       value_32bit );
898
899
      libcnotify_printf(
900
       "%s: time values data:\n",
901
       function );
902
      libcnotify_print_data(
903
             ( (agdb_database_header_228_t *) database_header_data )->unknown17,
904
             120,
905
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
906
    }
907
    libcnotify_printf(
908
     "\n" );
909
  }
910
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
911
912
1.28k
  memory_free(
913
1.28k
   database_header_data );
914
915
1.28k
  database_header_data = NULL;
916
917
1.28k
  *volumes_information_offset = header_size;
918
919
1.28k
  return( 1 );
920
921
848
on_error:
922
848
  if( database_header_data != NULL )
923
119
  {
924
119
    memory_free(
925
119
     database_header_data );
926
119
  }
927
848
  return( -1 );
928
1.40k
}
929
930
/* Reads data from the current offset into a buffer
931
 * Callback for the uncompressed block stream
932
 * Returns the number of bytes read or -1 on error
933
 */
934
ssize_t libagdb_io_handle_read_segment_data(
935
         intptr_t *data_handle LIBAGDB_ATTRIBUTE_UNUSED,
936
         intptr_t *file_io_handle,
937
         int segment_index,
938
         int segment_file_index LIBAGDB_ATTRIBUTE_UNUSED,
939
         uint8_t *segment_data,
940
         size_t segment_data_size,
941
         uint32_t segment_flags LIBAGDB_ATTRIBUTE_UNUSED,
942
         uint8_t read_flags LIBAGDB_ATTRIBUTE_UNUSED,
943
         libcerror_error_t **error )
944
956
{
945
956
  static char *function = "libagdb_io_handle_read_segment_data";
946
956
  ssize_t read_count    = 0;
947
948
956
  LIBAGDB_UNREFERENCED_PARAMETER( data_handle )
949
956
  LIBAGDB_UNREFERENCED_PARAMETER( segment_file_index )
950
956
  LIBAGDB_UNREFERENCED_PARAMETER( segment_flags )
951
956
  LIBAGDB_UNREFERENCED_PARAMETER( read_flags )
952
953
956
  if( segment_data_size > (size64_t) SSIZE_MAX )
954
0
  {
955
0
    libcerror_error_set(
956
0
     error,
957
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
958
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
959
0
     "%s: invalid segment data size value out of bounds.",
960
0
     function );
961
962
0
    return( -1 );
963
0
  }
964
956
  read_count = libbfio_handle_read_buffer(
965
956
                (libbfio_handle_t *) file_io_handle,
966
956
                segment_data,
967
956
                segment_data_size,
968
956
                error );
969
970
956
  if( read_count != (ssize_t) segment_data_size )
971
0
  {
972
0
    libcerror_error_set(
973
0
     error,
974
0
     LIBCERROR_ERROR_DOMAIN_IO,
975
0
     LIBCERROR_IO_ERROR_READ_FAILED,
976
0
     "%s: unable to read segment: %d data.",
977
0
     function,
978
0
     segment_index );
979
980
0
    return( -1 );
981
0
  }
982
956
  return( read_count );
983
956
}
984
985
/* Seeks a certain offset of the data
986
 * Callback for the uncompressed block stream
987
 * Returns the offset if seek is successful or -1 on error
988
 */
989
off64_t libagdb_io_handle_seek_segment_offset(
990
         intptr_t *data_handle LIBAGDB_ATTRIBUTE_UNUSED,
991
         intptr_t *file_io_handle,
992
         int segment_index,
993
         int segment_file_index LIBAGDB_ATTRIBUTE_UNUSED,
994
         off64_t segment_offset,
995
         libcerror_error_t **error )
996
956
{
997
956
  static char *function = "libagdb_io_handle_seek_segment_offset";
998
999
956
  LIBAGDB_UNREFERENCED_PARAMETER( data_handle )
1000
956
  LIBAGDB_UNREFERENCED_PARAMETER( segment_file_index )
1001
1002
956
  if( libbfio_handle_seek_offset(
1003
956
       (libbfio_handle_t *) file_io_handle,
1004
956
       segment_offset,
1005
956
       SEEK_SET,
1006
956
       error ) == -1 )
1007
0
  {
1008
0
    libcerror_error_set(
1009
0
     error,
1010
0
     LIBCERROR_ERROR_DOMAIN_IO,
1011
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
1012
0
     "%s: unable to seek segment: %d offset: %" PRIi64 ".",
1013
0
     function,
1014
0
     segment_index,
1015
0
     segment_offset );
1016
1017
0
    return( -1 );
1018
0
  }
1019
956
  return( segment_offset );
1020
956
}
1021