Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libagdb/libagdb/libagdb_file_information.c
Line
Count
Source
1
/*
2
 * File information functions
3
 *
4
 * Copyright (C) 2014-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libagdb_debug.h"
28
#include "libagdb_definitions.h"
29
#include "libagdb_file_information.h"
30
#include "libagdb_hash.h"
31
#include "libagdb_io_handle.h"
32
#include "libagdb_libbfio.h"
33
#include "libagdb_libcerror.h"
34
#include "libagdb_libcnotify.h"
35
#include "libagdb_libfcache.h"
36
#include "libagdb_libfdata.h"
37
#include "libagdb_libuna.h"
38
39
#include "agdb_file_information.h"
40
41
/* Creates file information
42
 * Make sure the value file_information is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libagdb_file_information_initialize(
46
     libagdb_file_information_t **file_information,
47
     libcerror_error_t **error )
48
29.9k
{
49
29.9k
  libagdb_internal_file_information_t *internal_file_information = NULL;
50
29.9k
  static char *function                                          = "libagdb_file_information_initialize";
51
52
29.9k
  if( file_information == NULL )
53
0
  {
54
0
    libcerror_error_set(
55
0
     error,
56
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58
0
     "%s: invalid file information.",
59
0
     function );
60
61
0
    return( -1 );
62
0
  }
63
29.9k
  if( *file_information != NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
68
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
69
0
     "%s: invalid file information value already set.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
29.9k
  internal_file_information = memory_allocate_structure(
75
29.9k
                               libagdb_internal_file_information_t );
76
77
29.9k
  if( internal_file_information == NULL )
78
0
  {
79
0
    libcerror_error_set(
80
0
     error,
81
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
82
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
83
0
     "%s: unable to create file information.",
84
0
     function );
85
86
0
    goto on_error;
87
0
  }
88
29.9k
  if( memory_set(
89
29.9k
       internal_file_information,
90
29.9k
       0,
91
29.9k
       sizeof( libagdb_internal_file_information_t ) ) == NULL )
92
0
  {
93
0
    libcerror_error_set(
94
0
     error,
95
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
96
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
97
0
     "%s: unable to clear file.",
98
0
     function );
99
100
0
    goto on_error;
101
0
  }
102
29.9k
  *file_information = (libagdb_file_information_t *) internal_file_information;
103
104
29.9k
  return( 1 );
105
106
0
on_error:
107
0
  if( internal_file_information != NULL )
108
0
  {
109
0
    memory_free(
110
0
     internal_file_information );
111
0
  }
112
0
  return( -1 );
113
29.9k
}
114
115
/* Frees file information
116
 * Returns 1 if successful or -1 on error
117
 */
118
int libagdb_file_information_free(
119
     libagdb_file_information_t **file_information,
120
     libcerror_error_t **error )
121
0
{
122
0
  static char *function = "libagdb_file_information_free";
123
124
0
  if( file_information == NULL )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
130
0
     "%s: invalid file information.",
131
0
     function );
132
133
0
    return( -1 );
134
0
  }
135
0
  if( *file_information != NULL )
136
0
  {
137
0
    *file_information = NULL;
138
0
  }
139
0
  return( 1 );
140
0
}
141
142
/* Frees file information
143
 * Returns 1 if successful or -1 on error
144
 */
145
int libagdb_internal_file_information_free(
146
     libagdb_internal_file_information_t **internal_file_information,
147
     libcerror_error_t **error )
148
29.9k
{
149
29.9k
  static char *function = "libagdb_internal_file_information_free";
150
151
29.9k
  if( internal_file_information == NULL )
152
0
  {
153
0
    libcerror_error_set(
154
0
     error,
155
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
156
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
157
0
     "%s: invalid file information.",
158
0
     function );
159
160
0
    return( -1 );
161
0
  }
162
29.9k
  if( *internal_file_information != NULL )
163
29.9k
  {
164
29.9k
    if( ( *internal_file_information )->path != NULL )
165
11.0k
    {
166
11.0k
      memory_free(
167
11.0k
       ( *internal_file_information )->path );
168
11.0k
    }
169
29.9k
    memory_free(
170
29.9k
     *internal_file_information );
171
172
29.9k
    *internal_file_information = NULL;
173
29.9k
  }
174
29.9k
  return( 1 );
175
29.9k
}
176
177
/* Reads the file information path data
178
 * Note that this function is mainly used for the tests
179
 * Returns the number of bytes read if successful or -1 on error
180
 */
181
int libagdb_internal_file_information_read_path_data(
182
     libagdb_internal_file_information_t *internal_file_information,
183
     const uint8_t *data,
184
     size_t data_size,
185
     libcerror_error_t **error )
186
0
{
187
0
  static char *function  = "libagdb_internal_file_information_read_path_data";
188
189
0
  if( internal_file_information == NULL )
190
0
  {
191
0
    libcerror_error_set(
192
0
     error,
193
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
194
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
195
0
     "%s: invalid file information.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
0
  if( internal_file_information->path != NULL )
201
0
  {
202
0
    libcerror_error_set(
203
0
     error,
204
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
205
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
206
0
     "%s: invalid file information - path value already set.",
207
0
     function );
208
209
0
    return( -1 );
210
0
  }
211
0
  if( data == NULL )
212
0
  {
213
0
    libcerror_error_set(
214
0
     error,
215
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
216
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
217
0
     "%s: invalid data.",
218
0
     function );
219
220
0
    return( -1 );
221
0
  }
222
0
  if( ( data_size < internal_file_information->path_size )
223
0
   || ( data_size > (size_t) SSIZE_MAX ) )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
228
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
229
0
     "%s: invalid data size value out bounds.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
#if defined( HAVE_DEBUG_OUTPUT )
235
  if( libcnotify_verbose != 0 )
236
  {
237
    libcnotify_printf(
238
     "%s: file information path data:\n",
239
     function );
240
    libcnotify_print_data(
241
     data,
242
     (size_t) internal_file_information->path_size,
243
     0 );
244
  }
245
#endif
246
0
  if( internal_file_information->path_size > 0 )
247
0
  {
248
0
    if( internal_file_information->path_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
249
0
    {
250
0
      libcerror_error_set(
251
0
       error,
252
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
253
0
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
254
0
       "%s: invalid file information - path size value exceeds maximum allocation size.",
255
0
       function );
256
257
0
      goto on_error;
258
0
    }
259
0
    internal_file_information->path = (uint8_t *) memory_allocate(
260
0
                                                   sizeof( uint8_t ) * internal_file_information->path_size );
261
262
0
    if( internal_file_information->path == NULL )
263
0
    {
264
0
      libcerror_error_set(
265
0
       error,
266
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
267
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
268
0
       "%s: unable to create path.",
269
0
       function );
270
271
0
      goto on_error;
272
0
    }
273
0
    if( memory_copy(
274
0
         internal_file_information->path,
275
0
         data,
276
0
         sizeof( uint8_t ) * internal_file_information->path_size ) == NULL )
277
0
    {
278
0
      libcerror_error_set(
279
0
       error,
280
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
281
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
282
0
       "%s: unable to copy path.",
283
0
       function );
284
285
0
      goto on_error;
286
0
    }
287
0
  }
288
0
  return( 1 );
289
290
0
on_error:
291
0
  if( internal_file_information->path != NULL )
292
0
  {
293
0
    memory_free(
294
0
     internal_file_information->path );
295
296
0
    internal_file_information->path = NULL;
297
0
  }
298
0
  internal_file_information->path_size = 0;
299
300
0
  return( -1 );
301
0
}
302
303
/* Reads the file information
304
 * Returns the number of bytes read if successful or -1 on error
305
 */
306
int libagdb_internal_file_information_read_data(
307
     libagdb_internal_file_information_t *internal_file_information,
308
     libagdb_io_handle_t *io_handle,
309
     const uint8_t *data,
310
     size_t data_size,
311
     uint8_t number_of_bits,
312
     libcerror_error_t **error )
313
29.7k
{
314
29.7k
  static char *function = "libagdb_internal_file_information_read_data";
315
316
#if defined( HAVE_DEBUG_OUTPUT )
317
  uint64_t value_64bit  = 0;
318
  uint32_t value_32bit  = 0;
319
#endif
320
321
29.7k
  if( internal_file_information == NULL )
322
0
  {
323
0
    libcerror_error_set(
324
0
     error,
325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
326
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
327
0
     "%s: invalid file information.",
328
0
     function );
329
330
0
    return( -1 );
331
0
  }
332
29.7k
  if( io_handle == NULL )
333
0
  {
334
0
    libcerror_error_set(
335
0
     error,
336
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
337
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
338
0
     "%s: invalid IO handle.",
339
0
     function );
340
341
0
    return( -1 );
342
0
  }
343
29.7k
  if( data == NULL )
344
0
  {
345
0
    libcerror_error_set(
346
0
     error,
347
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
348
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
349
0
     "%s: invalid data.",
350
0
     function );
351
352
0
    return( -1 );
353
0
  }
354
29.7k
  if( ( data_size < io_handle->file_information_entry_size )
355
29.7k
   || ( data_size > (size_t) SSIZE_MAX ) )
356
0
  {
357
0
    libcerror_error_set(
358
0
     error,
359
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
360
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
361
0
     "%s: invalid data size value out of bounds.",
362
0
     function );
363
364
0
    return( -1 );
365
0
  }
366
29.7k
  if( ( number_of_bits != 32 )
367
24.7k
   && ( number_of_bits != 64 ) )
368
0
  {
369
0
    libcerror_error_set(
370
0
     error,
371
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
373
0
     "%s: unsupported file information entry size: %" PRIu32 ".",
374
0
     function,
375
0
     io_handle->file_information_entry_size );
376
377
0
    return( -1 );
378
0
  }
379
#if defined( HAVE_DEBUG_OUTPUT )
380
  if( libcnotify_verbose != 0 )
381
  {
382
    libcnotify_printf(
383
     "%s: file information data:\n",
384
     function );
385
    libcnotify_print_data(
386
     data,
387
     (size_t) io_handle->file_information_entry_size,
388
     0 );
389
  }
390
#endif
391
29.7k
  switch( io_handle->file_header_signature )
392
29.7k
  {
393
0
    case 0x00000003UL:
394
758
    case 0x0000000fUL:
395
758
      if( ( io_handle->file_information_entry_size == 48 )
396
758
       || ( io_handle->file_information_entry_size == 72 ) )
397
383
      {
398
383
        byte_stream_copy_to_uint32_little_endian(
399
383
         ( (agdb_file_information_48_32bit_t *) data )->number_of_entries,
400
383
         internal_file_information->number_of_entries );
401
402
383
        byte_stream_copy_to_uint32_little_endian(
403
383
         ( (agdb_file_information_48_32bit_t *) data )->path_number_of_characters,
404
383
         internal_file_information->path_size );
405
383
      }
406
375
      else if( io_handle->file_information_entry_size == 56 )
407
0
      {
408
0
        byte_stream_copy_to_uint32_little_endian(
409
0
         ( (agdb_file_information_56_64bit_t *) data )->path_number_of_characters,
410
0
         internal_file_information->path_size );
411
412
0
        byte_stream_copy_to_uint32_little_endian(
413
0
         ( (agdb_file_information_56_64bit_t *) data )->number_of_entries,
414
0
         internal_file_information->number_of_entries );
415
0
      }
416
375
      else if( ( io_handle->file_information_entry_size == 80 )
417
375
            || ( io_handle->file_information_entry_size == 112 ) )
418
375
      {
419
375
        byte_stream_copy_to_uint32_little_endian(
420
375
         ( (agdb_file_information_80_64bit_t *) data )->path_number_of_characters,
421
375
         internal_file_information->path_size );
422
423
375
        byte_stream_copy_to_uint32_little_endian(
424
375
         ( (agdb_file_information_80_64bit_t *) data )->number_of_entries,
425
375
         internal_file_information->number_of_entries );
426
375
      }
427
758
      break;
428
429
28.9k
    case 0x0000000eUL:
430
28.9k
      if( number_of_bits == 32 )
431
4.59k
      {
432
4.59k
        byte_stream_copy_to_uint32_little_endian(
433
4.59k
         ( (agdb_file_information_36_32bit_t *) data )->number_of_entries,
434
4.59k
         internal_file_information->number_of_entries );
435
436
4.59k
        byte_stream_copy_to_uint32_little_endian(
437
4.59k
         ( (agdb_file_information_36_32bit_t *) data )->path_number_of_characters,
438
4.59k
         internal_file_information->path_size );
439
4.59k
      }
440
24.3k
      else if( number_of_bits == 64 )
441
24.3k
      {
442
24.3k
        byte_stream_copy_to_uint32_little_endian(
443
24.3k
         ( (agdb_file_information_64_64bit_t *) data )->number_of_entries,
444
24.3k
         internal_file_information->number_of_entries );
445
446
24.3k
        byte_stream_copy_to_uint32_little_endian(
447
24.3k
         ( (agdb_file_information_64_64bit_t *) data )->path_number_of_characters,
448
24.3k
         internal_file_information->path_size );
449
24.3k
      }
450
28.9k
      break;
451
29.7k
  }
452
#if defined( HAVE_DEBUG_OUTPUT )
453
  if( libcnotify_verbose != 0 )
454
  {
455
    if( number_of_bits == 32 )
456
    {
457
      byte_stream_copy_to_uint32_little_endian(
458
       ( (agdb_file_information_36_32bit_t *) data )->unknown1,
459
       value_64bit );
460
    }
461
    else if( number_of_bits == 64 )
462
    {
463
      byte_stream_copy_to_uint64_little_endian(
464
       ( (agdb_file_information_64_64bit_t *) data )->unknown1,
465
       value_64bit );
466
    }
467
    libcnotify_printf(
468
     "%s: unknown1\t\t\t\t: 0x%08" PRIx64 "\n",
469
     function,
470
     value_64bit );
471
472
    if( number_of_bits == 32 )
473
    {
474
      byte_stream_copy_to_uint32_little_endian(
475
       ( (agdb_file_information_36_32bit_t *) data )->name_hash,
476
       value_64bit );
477
    }
478
    else if( number_of_bits == 64 )
479
    {
480
      byte_stream_copy_to_uint64_little_endian(
481
       ( (agdb_file_information_64_64bit_t *) data )->name_hash,
482
       value_64bit );
483
    }
484
    libcnotify_printf(
485
     "%s: name hash\t\t\t\t: 0x%08" PRIx64 "\n",
486
     function,
487
     value_64bit );
488
489
    if( ( io_handle->file_header_signature == 0x00000003UL )
490
     || ( io_handle->file_header_signature == 0x0000000fUL ) )
491
    {
492
      libcnotify_printf(
493
       "%s: path number of characters\t\t: 0x%08" PRIx32 " (number of characters: %" PRIu32 ", lower bits: 0x%02" PRIx32 ")\n",
494
       function,
495
       internal_file_information->path_size,
496
       internal_file_information->path_size >> 2,
497
       internal_file_information->path_size & 0x00000003UL );
498
499
      if( number_of_bits == 32 )
500
      {
501
        byte_stream_copy_to_uint32_little_endian(
502
         ( (agdb_file_information_48_32bit_t *) data )->unknown2,
503
         value_32bit );
504
      }
505
      else if( number_of_bits == 64 )
506
      {
507
        byte_stream_copy_to_uint32_little_endian(
508
         ( (agdb_file_information_56_64bit_t *) data )->unknown2,
509
         value_32bit );
510
      }
511
      libcnotify_printf(
512
       "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
513
       function,
514
       value_32bit );
515
    }
516
    else if( io_handle->file_header_signature == 0x0000000eUL )
517
    {
518
      libcnotify_printf(
519
       "%s: number of entries\t\t\t: %" PRIu32 "\n",
520
       function,
521
       internal_file_information->number_of_entries );
522
523
      if( number_of_bits == 32 )
524
      {
525
        byte_stream_copy_to_uint32_little_endian(
526
         ( (agdb_file_information_36_32bit_t *) data )->flags,
527
         value_32bit );
528
      }
529
      else if( number_of_bits == 64 )
530
      {
531
        byte_stream_copy_to_uint32_little_endian(
532
         ( (agdb_file_information_64_64bit_t *) data )->flags,
533
         value_32bit );
534
      }
535
      libcnotify_printf(
536
       "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n",
537
       function,
538
       value_32bit );
539
    }
540
    if( number_of_bits == 32 )
541
    {
542
      byte_stream_copy_to_uint32_little_endian(
543
       ( (agdb_file_information_36_32bit_t *) data )->unknown3,
544
       value_64bit );
545
    }
546
    else if( number_of_bits == 64 )
547
    {
548
      byte_stream_copy_to_uint64_little_endian(
549
       ( (agdb_file_information_64_64bit_t *) data )->unknown3,
550
       value_64bit );
551
    }
552
    libcnotify_printf(
553
     "%s: unknown3\t\t\t\t: 0x%08" PRIx64 "\n",
554
     function,
555
     value_64bit );
556
557
    if( ( io_handle->file_information_entry_size == 36 )
558
     || ( io_handle->file_information_entry_size == 48 )
559
     || ( io_handle->file_information_entry_size == 52 )
560
     || ( io_handle->file_information_entry_size == 72 ) )
561
    {
562
      byte_stream_copy_to_uint32_little_endian(
563
       ( (agdb_file_information_36_32bit_t *) data )->unknown4,
564
       value_32bit );
565
      libcnotify_printf(
566
       "%s: unknown4\t\t\t\t: 0x%08" PRIx32 "\n",
567
       function,
568
       value_32bit );
569
    }
570
    else if( io_handle->file_information_entry_size == 56 )
571
    {
572
      libcnotify_printf(
573
       "%s: number of entries\t\t\t: %" PRIu32 "\n",
574
       function,
575
       internal_file_information->number_of_entries );
576
577
      byte_stream_copy_to_uint32_little_endian(
578
       ( (agdb_file_information_56_64bit_t *) data )->unknown4,
579
       value_32bit );
580
      libcnotify_printf(
581
       "%s: unknown4\t\t\t\t: 0x%08" PRIx32 "\n",
582
       function,
583
       value_32bit );
584
    }
585
    else if( ( io_handle->file_information_entry_size == 64 )
586
          || ( io_handle->file_information_entry_size == 80 )
587
          || ( io_handle->file_information_entry_size == 88 )
588
          || ( io_handle->file_information_entry_size == 112 ) )
589
    {
590
      byte_stream_copy_to_uint64_little_endian(
591
       ( (agdb_file_information_64_64bit_t *) data )->unknown4,
592
       value_64bit );
593
      libcnotify_printf(
594
       "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
595
       function,
596
       value_64bit );
597
    }
598
    if( ( io_handle->file_information_entry_size == 36 )
599
     || ( io_handle->file_information_entry_size == 48 )
600
     || ( io_handle->file_information_entry_size == 52 )
601
     || ( io_handle->file_information_entry_size == 72 ) )
602
    {
603
      byte_stream_copy_to_uint32_little_endian(
604
       ( (agdb_file_information_36_32bit_t *) data )->unknown5,
605
       value_32bit );
606
      libcnotify_printf(
607
       "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
608
       function,
609
       value_32bit );
610
    }
611
    else if( ( io_handle->file_information_entry_size == 56 )
612
          || ( io_handle->file_information_entry_size == 64 )
613
          || ( io_handle->file_information_entry_size == 80 )
614
          || ( io_handle->file_information_entry_size == 88 )
615
          || ( io_handle->file_information_entry_size == 112 ) )
616
    {
617
      byte_stream_copy_to_uint64_little_endian(
618
       ( (agdb_file_information_56_64bit_t *) data )->unknown5,
619
       value_64bit );
620
      libcnotify_printf(
621
       "%s: unknown5\t\t\t\t: 0x%08" PRIx64 "\n",
622
       function,
623
       value_64bit );
624
    }
625
    if( ( io_handle->file_header_signature == 0x00000003UL )
626
     || ( io_handle->file_header_signature == 0x0000000fUL ) )
627
    {
628
      if( number_of_bits == 32 )
629
      {
630
        byte_stream_copy_to_uint32_little_endian(
631
         ( (agdb_file_information_48_32bit_t *) data )->unknown6,
632
         value_32bit );
633
      }
634
      else if( number_of_bits == 64 )
635
      {
636
        byte_stream_copy_to_uint32_little_endian(
637
         ( (agdb_file_information_56_64bit_t *) data )->unknown6,
638
         value_32bit );
639
      }
640
      libcnotify_printf(
641
       "%s: unknown6\t\t\t\t: 0x%08" PRIx32 "\n",
642
       function,
643
       value_32bit );
644
    }
645
    else if( io_handle->file_header_signature == 0x0000000eUL )
646
    {
647
      libcnotify_printf(
648
       "%s: path number of characters\t\t: 0x%08" PRIx32 " (number of characters: %" PRIu32 ", lower bits: 0x%02" PRIx32 ")\n",
649
       function,
650
       internal_file_information->path_size,
651
       internal_file_information->path_size >> 2,
652
       internal_file_information->path_size & 0x00000003UL );
653
    }
654
    if( ( io_handle->file_information_entry_size == 36 )
655
     || ( io_handle->file_information_entry_size == 48 )
656
     || ( io_handle->file_information_entry_size == 52 )
657
     || ( io_handle->file_information_entry_size == 72 ) )
658
    {
659
      byte_stream_copy_to_uint32_little_endian(
660
       ( (agdb_file_information_36_32bit_t *) data )->unknown7,
661
       value_32bit );
662
    }
663
    else if( ( io_handle->file_information_entry_size == 56 )
664
          || ( io_handle->file_information_entry_size == 64 )
665
          || ( io_handle->file_information_entry_size == 80 )
666
          || ( io_handle->file_information_entry_size == 88 )
667
          || ( io_handle->file_information_entry_size == 112 ) )
668
    {
669
      byte_stream_copy_to_uint32_little_endian(
670
       ( (agdb_file_information_56_64bit_t *) data )->unknown7,
671
       value_32bit );
672
    }
673
    libcnotify_printf(
674
     "%s: unknown7\t\t\t\t: 0x%08" PRIx32 "\n",
675
     function,
676
     value_32bit );
677
678
    if( ( io_handle->file_information_entry_size == 48 )
679
     || ( io_handle->file_information_entry_size == 52 )
680
     || ( io_handle->file_information_entry_size == 72 ) )
681
    {
682
      byte_stream_copy_to_uint32_little_endian(
683
       ( (agdb_file_information_48_32bit_t *) data )->unknown8,
684
       value_32bit );
685
      libcnotify_printf(
686
       "%s: unknown8\t\t\t\t: 0x%08" PRIx32 "\n",
687
       function,
688
       value_32bit );
689
690
      byte_stream_copy_to_uint32_little_endian(
691
       ( (agdb_file_information_48_32bit_t *) data )->unknown9,
692
       value_32bit );
693
      libcnotify_printf(
694
       "%s: unknown9\t\t\t\t: 0x%08" PRIx32 "\n",
695
       function,
696
       value_32bit );
697
    }
698
    else if( ( io_handle->file_information_entry_size == 80 )
699
          || ( io_handle->file_information_entry_size == 88 )
700
          || ( io_handle->file_information_entry_size == 112 ) )
701
    {
702
      byte_stream_copy_to_uint64_little_endian(
703
       ( (agdb_file_information_80_64bit_t *) data )->unknown8,
704
       value_64bit );
705
      libcnotify_printf(
706
       "%s: unknown8\t\t\t\t: 0x%08" PRIx64 "\n",
707
       function,
708
       value_64bit );
709
710
      byte_stream_copy_to_uint64_little_endian(
711
       ( (agdb_file_information_80_64bit_t *) data )->unknown9,
712
       value_64bit );
713
      libcnotify_printf(
714
       "%s: unknown9\t\t\t\t: 0x%08" PRIx64 "\n",
715
       function,
716
       value_64bit );
717
    }
718
    if( ( io_handle->file_header_signature == 0x00000003UL )
719
     || ( io_handle->file_header_signature == 0x0000000fUL ) )
720
    {
721
      if( io_handle->file_information_entry_size == 80 )
722
      {
723
        byte_stream_copy_to_uint32_little_endian(
724
         ( (agdb_file_information_80_64bit_t *) data )->unknown10,
725
         value_32bit );
726
        libcnotify_printf(
727
         "%s: unknown10\t\t\t\t: 0x%08" PRIx32 "\n",
728
         function,
729
         value_32bit );
730
      }
731
      if( io_handle->file_information_entry_size > 56 )
732
      {
733
        libcnotify_printf(
734
         "%s: number of entries\t\t\t: %" PRIu32 "\n",
735
         function,
736
         internal_file_information->number_of_entries );
737
      }
738
    }
739
    else if( io_handle->file_header_signature == 0x0000000eUL )
740
    {
741
      if( ( io_handle->file_information_entry_size == 52 )
742
       || ( io_handle->file_information_entry_size == 72 ) )
743
      {
744
        byte_stream_copy_to_uint32_little_endian(
745
         ( (agdb_file_information_52_32bit_t *) data )->unknown10,
746
         value_64bit );
747
      }
748
      else if( ( io_handle->file_information_entry_size == 88 )
749
            || ( io_handle->file_information_entry_size == 112 ) )
750
      {
751
        byte_stream_copy_to_uint64_little_endian(
752
         ( (agdb_file_information_88_64bit_t *) data )->unknown10,
753
         value_64bit );
754
      }
755
      libcnotify_printf(
756
       "%s: unknown10\t\t\t\t: 0x%08" PRIx64 "\n",
757
       function,
758
       value_64bit );
759
    }
760
    if( ( io_handle->file_information_entry_size == 52 )
761
     || ( io_handle->file_information_entry_size == 72 ) )
762
    {
763
      byte_stream_copy_to_uint32_little_endian(
764
       ( (agdb_file_information_52_32bit_t *) data )->unknown11,
765
       value_32bit );
766
      libcnotify_printf(
767
       "%s: unknown11\t\t\t\t: 0x%08" PRIx32 "\n",
768
       function,
769
       value_32bit );
770
    }
771
    else if( ( io_handle->file_information_entry_size == 88 )
772
          || ( io_handle->file_information_entry_size == 112 ) )
773
    {
774
      byte_stream_copy_to_uint64_little_endian(
775
       ( (agdb_file_information_88_64bit_t *) data )->unknown11,
776
       value_64bit );
777
      libcnotify_printf(
778
       "%s: unknown11\t\t\t\t: 0x%08" PRIx64 "\n",
779
       function,
780
       value_64bit );
781
    }
782
    if( io_handle->file_information_entry_size == 72 )
783
    {
784
      byte_stream_copy_to_uint32_little_endian(
785
       ( (agdb_file_information_72_32bit_t *) data )->unknown12,
786
       value_32bit );
787
      libcnotify_printf(
788
       "%s: unknown12\t\t\t\t: 0x%08" PRIx32 "\n",
789
       function,
790
       value_32bit );
791
792
      byte_stream_copy_to_uint32_little_endian(
793
       ( (agdb_file_information_72_32bit_t *) data )->unknown13,
794
       value_32bit );
795
      libcnotify_printf(
796
       "%s: unknown13\t\t\t\t: 0x%08" PRIx32 "\n",
797
       function,
798
       value_32bit );
799
800
      byte_stream_copy_to_uint32_little_endian(
801
       ( (agdb_file_information_72_32bit_t *) data )->unknown14,
802
       value_32bit );
803
      libcnotify_printf(
804
       "%s: unknown14\t\t\t\t: 0x%08" PRIx32 "\n",
805
       function,
806
       value_32bit );
807
808
      byte_stream_copy_to_uint32_little_endian(
809
       ( (agdb_file_information_72_32bit_t *) data )->unknown15,
810
       value_32bit );
811
      libcnotify_printf(
812
       "%s: unknown15\t\t\t\t: 0x%08" PRIx32 "\n",
813
       function,
814
       value_32bit );
815
816
      byte_stream_copy_to_uint32_little_endian(
817
       ( (agdb_file_information_72_32bit_t *) data )->unknown16,
818
       value_32bit );
819
      libcnotify_printf(
820
       "%s: unknown16\t\t\t\t: 0x%08" PRIx32 "\n",
821
       function,
822
       value_32bit );
823
    }
824
    else if( io_handle->file_information_entry_size == 112 )
825
    {
826
      byte_stream_copy_to_uint64_little_endian(
827
       ( (agdb_file_information_112_64bit_t *) data )->unknown12,
828
       value_64bit );
829
      libcnotify_printf(
830
       "%s: unknown12\t\t\t\t: 0x%08" PRIx64 "\n",
831
       function,
832
       value_64bit );
833
834
      byte_stream_copy_to_uint64_little_endian(
835
       ( (agdb_file_information_112_64bit_t *) data )->unknown13,
836
       value_64bit );
837
      libcnotify_printf(
838
       "%s: unknown13\t\t\t\t: 0x%08" PRIx64 "\n",
839
       function,
840
       value_64bit );
841
842
      byte_stream_copy_to_uint64_little_endian(
843
       ( (agdb_file_information_112_64bit_t *) data )->unknown14,
844
       value_64bit );
845
      libcnotify_printf(
846
       "%s: unknown14\t\t\t\t: 0x%08" PRIx64 "\n",
847
       function,
848
       value_64bit );
849
    }
850
    libcnotify_printf(
851
     "\n" );
852
  }
853
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
854
855
29.7k
  if( internal_file_information->path_size != 0 )
856
11.2k
  {
857
11.2k
    internal_file_information->path_size >>= 2;
858
11.2k
    internal_file_information->path_size <<= 1;
859
11.2k
    internal_file_information->path_size  += 2;
860
11.2k
  }
861
29.7k
  return( 1 );
862
29.7k
}
863
864
/* Reads the file information
865
 * Returns the number of bytes read if successful or -1 on error
866
 */
867
ssize_t libagdb_internal_file_information_read_file_io_handle(
868
         libagdb_internal_file_information_t *internal_file_information,
869
         libagdb_io_handle_t *io_handle,
870
         libfdata_stream_t *data_stream,
871
         libbfio_handle_t *file_io_handle,
872
         off64_t file_offset,
873
         uint32_t file_index,
874
         libcerror_error_t **error )
875
29.9k
{
876
29.9k
  uint8_t alignment_padding_data[ 8 ];
877
29.9k
  uint8_t sub_entry_data[ 32 ];
878
879
29.9k
  uint8_t *file_information_data = NULL;
880
29.9k
  static char *function          = "libagdb_internal_file_information_read_file_io_handle";
881
29.9k
  size_t alignment_padding_size  = 0;
882
29.9k
  size_t alignment_size          = 0;
883
29.9k
  ssize_t read_count             = 0;
884
29.9k
  ssize_t total_read_count       = 0;
885
29.9k
  uint32_t calculated_hash_value = 0;
886
29.9k
  uint32_t entry_index           = 0;
887
29.9k
  uint32_t sub_entry_data_size   = 0;
888
29.9k
  uint8_t number_of_bits         = 0;
889
890
#if defined( HAVE_DEBUG_OUTPUT )
891
  uint32_t value_32bit           = 0;
892
  uint16_t value_16bit           = 0;
893
#endif
894
895
29.9k
  if( internal_file_information == NULL )
896
0
  {
897
0
    libcerror_error_set(
898
0
     error,
899
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
900
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
901
0
     "%s: invalid file information.",
902
0
     function );
903
904
0
    return( -1 );
905
0
  }
906
29.9k
  if( internal_file_information->path != NULL )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
911
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
912
0
     "%s: invalid file information - path value already set.",
913
0
     function );
914
915
0
    return( -1 );
916
0
  }
917
29.9k
  if( io_handle == NULL )
918
0
  {
919
0
    libcerror_error_set(
920
0
     error,
921
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
922
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
923
0
     "%s: invalid IO handle.",
924
0
     function );
925
926
0
    return( -1 );
927
0
  }
928
29.9k
  if( ( io_handle->file_information_entry_size == 0 )
929
29.9k
   || ( io_handle->file_information_entry_size > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
930
37
  {
931
37
    libcerror_error_set(
932
37
     error,
933
37
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
934
37
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
935
37
     "%s: invalid IO handle - file information entry size value out of bounds.",
936
37
     function );
937
938
37
    return( -1 );
939
37
  }
940
29.9k
  switch( io_handle->file_header_signature )
941
29.9k
  {
942
0
    case 0x00000003UL:
943
0
      if( ( io_handle->file_information_entry_size == 48 )
944
0
       || ( io_handle->file_information_entry_size == 72 ) )
945
0
      {
946
0
        number_of_bits = 32;
947
0
      }
948
0
      else if( ( io_handle->file_information_entry_size == 56 )
949
0
            || ( io_handle->file_information_entry_size == 80 )
950
0
            || ( io_handle->file_information_entry_size == 112 ) )
951
0
      {
952
0
        number_of_bits = 64;
953
0
      }
954
0
      break;
955
956
29.1k
    case 0x0000000eUL:
957
29.1k
      if( ( io_handle->file_information_entry_size == 36 )
958
28.4k
       || ( io_handle->file_information_entry_size == 52 )
959
25.4k
       || ( io_handle->file_information_entry_size == 72 ) )
960
4.63k
      {
961
4.63k
        number_of_bits = 32;
962
4.63k
      }
963
24.4k
      else if( ( io_handle->file_information_entry_size == 64 )
964
10.7k
            || ( io_handle->file_information_entry_size == 88 )
965
911
            || ( io_handle->file_information_entry_size == 112 ) )
966
24.4k
      {
967
24.4k
        number_of_bits = 64;
968
24.4k
      }
969
29.1k
      break;
970
971
819
    case 0x0000000fUL:
972
819
      if( io_handle->file_information_entry_size == 72 )
973
393
      {
974
393
        number_of_bits = 32;
975
393
      }
976
426
      else if( io_handle->file_information_entry_size == 112 )
977
388
      {
978
388
        number_of_bits = 64;
979
388
      }
980
819
      break;
981
982
0
    default:
983
0
      break;
984
985
29.9k
  }
986
29.9k
  if( number_of_bits == 0 )
987
106
  {
988
106
    libcerror_error_set(
989
106
     error,
990
106
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
991
106
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
992
106
     "%s: unsupported file information entry size: %" PRIu32 ".",
993
106
     function,
994
106
     io_handle->file_information_entry_size );
995
996
106
    return( -1 );
997
106
  }
998
29.8k
  file_information_data = (uint8_t *) memory_allocate(
999
29.8k
                                       sizeof( uint8_t ) * (size_t) io_handle->file_information_entry_size );
1000
1001
29.8k
  if( file_information_data == NULL )
1002
0
  {
1003
0
    libcerror_error_set(
1004
0
     error,
1005
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1006
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1007
0
     "%s: unable to create file information data.",
1008
0
     function );
1009
1010
0
    goto on_error;
1011
0
  }
1012
#if defined( HAVE_DEBUG_OUTPUT )
1013
  if( libcnotify_verbose != 0 )
1014
  {
1015
    libcnotify_printf(
1016
     "%s: reading file: %" PRIu32 " information at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
1017
     function,
1018
     file_index,
1019
     file_offset,
1020
     file_offset );
1021
  }
1022
#endif
1023
29.8k
  read_count = libfdata_stream_read_buffer_at_offset(
1024
29.8k
                data_stream,
1025
29.8k
                (intptr_t *) file_io_handle,
1026
29.8k
                file_information_data,
1027
29.8k
                (size_t) io_handle->file_information_entry_size,
1028
29.8k
                file_offset,
1029
29.8k
                0,
1030
29.8k
                error );
1031
1032
29.8k
  if( read_count != (ssize_t) io_handle->file_information_entry_size )
1033
80
  {
1034
80
    libcerror_error_set(
1035
80
     error,
1036
80
     LIBCERROR_ERROR_DOMAIN_IO,
1037
80
     LIBCERROR_IO_ERROR_READ_FAILED,
1038
80
     "%s: unable to read file: %" PRIu32 " information data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
1039
80
     function,
1040
80
     file_index,
1041
80
     file_offset,
1042
80
     file_offset );
1043
1044
80
    goto on_error;
1045
80
  }
1046
29.7k
  total_read_count += read_count;
1047
29.7k
  file_offset      += read_count;
1048
1049
29.7k
  if( libagdb_internal_file_information_read_data(
1050
29.7k
       internal_file_information,
1051
29.7k
       io_handle,
1052
29.7k
       file_information_data,
1053
29.7k
       (size_t) io_handle->file_information_entry_size,
1054
29.7k
       number_of_bits,
1055
29.7k
       error ) != 1 )
1056
0
  {
1057
0
    libcerror_error_set(
1058
0
     error,
1059
0
     LIBCERROR_ERROR_DOMAIN_IO,
1060
0
     LIBCERROR_IO_ERROR_READ_FAILED,
1061
0
     "%s: unable to read file: %" PRIu32 " information.",
1062
0
     function,
1063
0
     file_index );
1064
1065
0
    goto on_error;
1066
0
  }
1067
29.7k
  memory_free(
1068
29.7k
   file_information_data );
1069
1070
29.7k
  file_information_data = NULL;
1071
1072
29.7k
  if( internal_file_information->path_size > 0 )
1073
11.2k
  {
1074
11.2k
    if( internal_file_information->path_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
1075
41
    {
1076
41
      libcerror_error_set(
1077
41
       error,
1078
41
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1079
41
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1080
41
       "%s: invalid file information - path size value exceeds maximum allocation size.",
1081
41
       function );
1082
1083
41
      goto on_error;
1084
41
    }
1085
11.2k
    internal_file_information->path = (uint8_t *) memory_allocate(
1086
11.2k
                                                   sizeof( uint8_t ) * internal_file_information->path_size );
1087
1088
11.2k
    if( internal_file_information->path == NULL )
1089
0
    {
1090
0
      libcerror_error_set(
1091
0
       error,
1092
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1093
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1094
0
       "%s: unable to create path.",
1095
0
       function );
1096
1097
0
      goto on_error;
1098
0
    }
1099
11.2k
    read_count = libfdata_stream_read_buffer(
1100
11.2k
                  data_stream,
1101
11.2k
                  (intptr_t *) file_io_handle,
1102
11.2k
                  internal_file_information->path,
1103
11.2k
                  internal_file_information->path_size,
1104
11.2k
                  0,
1105
11.2k
                  error );
1106
1107
11.2k
    if( read_count != (ssize_t) internal_file_information->path_size )
1108
96
    {
1109
96
      libcerror_error_set(
1110
96
       error,
1111
96
       LIBCERROR_ERROR_DOMAIN_IO,
1112
96
       LIBCERROR_IO_ERROR_READ_FAILED,
1113
96
       "%s: unable to read file: %" PRIu32 " path data.",
1114
96
       function,
1115
96
       file_index );
1116
1117
96
      goto on_error;
1118
96
    }
1119
11.1k
    total_read_count += read_count;
1120
11.1k
    file_offset      += read_count;
1121
1122
#if defined( HAVE_DEBUG_OUTPUT )
1123
    if( libcnotify_verbose != 0 )
1124
    {
1125
      libcnotify_printf(
1126
       "%s: file: %" PRIu32 " path data:\n",
1127
       function,
1128
       file_index );
1129
      libcnotify_print_data(
1130
       internal_file_information->path,
1131
       internal_file_information->path_size,
1132
       0 );
1133
    }
1134
#endif
1135
11.1k
    if( libagdb_hash_calculate(
1136
11.1k
         &calculated_hash_value,
1137
11.1k
         internal_file_information->path,
1138
11.1k
         internal_file_information->path_size - 2,
1139
11.1k
         error ) != 1 )
1140
0
    {
1141
0
      libcerror_error_set(
1142
0
       error,
1143
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1144
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1145
0
       "%s: unable to retrieve path hash value.",
1146
0
       function );
1147
1148
0
      goto on_error;
1149
0
    }
1150
#if defined( HAVE_DEBUG_OUTPUT )
1151
    if( libcnotify_verbose != 0 )
1152
    {
1153
      if( libagdb_debug_print_utf16_string_value(
1154
           function,
1155
           "file path\t\t",
1156
           internal_file_information->path,
1157
           internal_file_information->path_size,
1158
           LIBUNA_ENDIAN_LITTLE,
1159
           error ) != 1 )
1160
      {
1161
        libcerror_error_set(
1162
         error,
1163
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1164
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
1165
         "%s: unable to print UTF-16 string value.",
1166
         function );
1167
1168
        goto on_error;
1169
      }
1170
      libcnotify_printf(
1171
       "%s: file path hash value\t: 0x%08" PRIx64 "\n",
1172
       function,
1173
       calculated_hash_value );
1174
1175
      libcnotify_printf(
1176
       "\n" );
1177
    }
1178
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1179
1180
11.1k
    if( number_of_bits == 32 )
1181
1.86k
    {
1182
1.86k
      alignment_size = 4;
1183
1.86k
    }
1184
9.28k
    else if( number_of_bits == 64 )
1185
9.28k
    {
1186
9.28k
      alignment_size = 8;
1187
9.28k
    }
1188
11.1k
    alignment_padding_size = (size_t) ( file_offset % alignment_size );
1189
1190
11.1k
    if( alignment_padding_size != 0 )
1191
8.19k
    {
1192
8.19k
      alignment_padding_size = alignment_size - alignment_padding_size;
1193
1194
#if defined( HAVE_DEBUG_OUTPUT )
1195
      if( libcnotify_verbose != 0 )
1196
      {
1197
        libcnotify_printf(
1198
         "%s: alignment padding size\t: %" PRIzd "\n",
1199
         function,
1200
         alignment_padding_size );
1201
      }
1202
#endif
1203
8.19k
      read_count = libfdata_stream_read_buffer(
1204
8.19k
                    data_stream,
1205
8.19k
                    (intptr_t *) file_io_handle,
1206
8.19k
                    alignment_padding_data,
1207
8.19k
                    alignment_padding_size,
1208
8.19k
                    0,
1209
8.19k
                    error );
1210
1211
8.19k
      if( read_count != (ssize_t) alignment_padding_size )
1212
11
      {
1213
11
        libcerror_error_set(
1214
11
         error,
1215
11
         LIBCERROR_ERROR_DOMAIN_IO,
1216
11
         LIBCERROR_IO_ERROR_READ_FAILED,
1217
11
         "%s: unable to read file: %" PRIu32 " alignment padding data.",
1218
11
         function,
1219
11
         file_index );
1220
1221
11
        goto on_error;
1222
11
      }
1223
8.18k
      total_read_count += read_count;
1224
8.18k
      file_offset      += read_count;
1225
1226
#if defined( HAVE_DEBUG_OUTPUT )
1227
      if( libcnotify_verbose != 0 )
1228
      {
1229
        libcnotify_printf(
1230
         "%s: file: %" PRIu32 " alignment padding data:\n",
1231
         function,
1232
         file_index );
1233
        libcnotify_print_data(
1234
         alignment_padding_data,
1235
         alignment_padding_size,
1236
         0 );
1237
      }
1238
#endif
1239
8.18k
    }
1240
11.1k
  }
1241
29.6k
  if( internal_file_information->number_of_entries > 0 )
1242
9.28k
  {
1243
9.28k
    if( ( io_handle->file_information_sub_entry_type1_size != 16 )
1244
7.06k
     && ( io_handle->file_information_sub_entry_type1_size != 24 ) )
1245
42
    {
1246
42
      libcerror_error_set(
1247
42
       error,
1248
42
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1249
42
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1250
42
       "%s: unsupported file information sub entry type 1 size: %" PRIu32 ".",
1251
42
       function,
1252
42
       io_handle->file_information_sub_entry_type1_size );
1253
1254
42
      return( -1 );
1255
42
    }
1256
9.23k
    if( ( io_handle->file_information_sub_entry_type2_size != 16 )
1257
8.34k
     && ( io_handle->file_information_sub_entry_type2_size != 20 )
1258
7.70k
     && ( io_handle->file_information_sub_entry_type2_size != 24 )
1259
5.49k
     && ( io_handle->file_information_sub_entry_type2_size != 32 ) )
1260
51
    {
1261
51
      libcerror_error_set(
1262
51
       error,
1263
51
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1264
51
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1265
51
       "%s: unsupported file information sub entry type 2 size: %" PRIu32 ".",
1266
51
       function,
1267
51
       io_handle->file_information_sub_entry_type2_size );
1268
1269
51
      return( -1 );
1270
51
    }
1271
9.18k
    for( entry_index = 0;
1272
578k
         entry_index < internal_file_information->number_of_entries;
1273
568k
         entry_index++ )
1274
569k
    {
1275
569k
      read_count = libfdata_stream_read_buffer(
1276
569k
              data_stream,
1277
569k
              (intptr_t *) file_io_handle,
1278
569k
              sub_entry_data,
1279
569k
              8,
1280
569k
              0,
1281
569k
              error );
1282
1283
569k
      if( read_count != (ssize_t) 8 )
1284
88
      {
1285
88
        libcerror_error_set(
1286
88
         error,
1287
88
         LIBCERROR_ERROR_DOMAIN_IO,
1288
88
         LIBCERROR_IO_ERROR_READ_FAILED,
1289
88
         "%s: unable to read sub entry: %" PRIu32 " data.",
1290
88
         function,
1291
88
         entry_index );
1292
1293
88
        goto on_error;
1294
88
      }
1295
569k
      if( ( io_handle->file_header_signature == 0x0000000eUL )
1296
568k
       && ( ( sub_entry_data[ 4 ] & 0x20 ) != 0 ) )
1297
119k
      {
1298
119k
        sub_entry_data_size = io_handle->file_information_sub_entry_type2_size;
1299
119k
      }
1300
449k
      else
1301
449k
      {
1302
449k
        sub_entry_data_size = io_handle->file_information_sub_entry_type1_size;
1303
449k
      }
1304
569k
      read_count = libfdata_stream_read_buffer(
1305
569k
              data_stream,
1306
569k
              (intptr_t *) file_io_handle,
1307
569k
              &( sub_entry_data[ 8 ] ),
1308
569k
              (size_t) sub_entry_data_size - 8,
1309
569k
              0,
1310
569k
              error );
1311
1312
569k
      if( read_count != ( (ssize_t) sub_entry_data_size - 8 ) )
1313
56
      {
1314
56
        libcerror_error_set(
1315
56
         error,
1316
56
         LIBCERROR_ERROR_DOMAIN_IO,
1317
56
         LIBCERROR_IO_ERROR_READ_FAILED,
1318
56
         "%s: unable to read sub entry: %" PRIu32 " data.",
1319
56
         function,
1320
56
         entry_index );
1321
1322
56
          goto on_error;
1323
56
      }
1324
#if defined( HAVE_DEBUG_OUTPUT )
1325
      if( libcnotify_verbose != 0 )
1326
      {
1327
        libcnotify_printf(
1328
         "%s: sub entry: %" PRIu32 " data:\n",
1329
         function,
1330
         entry_index );
1331
        libcnotify_print_data(
1332
         sub_entry_data,
1333
         (size_t) sub_entry_data_size,
1334
         0 );
1335
      }
1336
#endif
1337
#if defined( HAVE_DEBUG_OUTPUT )
1338
      if( libcnotify_verbose != 0 )
1339
      {
1340
        if( sub_entry_data_size >= 16 )
1341
        {
1342
          byte_stream_copy_to_uint32_little_endian(
1343
           sub_entry_data,
1344
           value_32bit );
1345
          libcnotify_printf(
1346
           "%s: unknown1\t\t: 0x%08" PRIx32 "\n",
1347
           function,
1348
           value_32bit );
1349
1350
          byte_stream_copy_to_uint32_little_endian(
1351
           &( sub_entry_data[ 4 ] ),
1352
           value_32bit );
1353
          libcnotify_printf(
1354
           "%s: unknown2\t\t: 0x%08" PRIx32 "\n",
1355
           function,
1356
           value_32bit );
1357
1358
          byte_stream_copy_to_uint16_little_endian(
1359
           &( sub_entry_data[ 8 ] ),
1360
           value_16bit );
1361
          libcnotify_printf(
1362
           "%s: unknown3\t\t: 0x%04" PRIx16 "\n",
1363
           function,
1364
           value_16bit );
1365
1366
          byte_stream_copy_to_uint16_little_endian(
1367
           &( sub_entry_data[ 10 ] ),
1368
           value_16bit );
1369
          libcnotify_printf(
1370
           "%s: unknown4\t\t: 0x%04" PRIx16 "\n",
1371
           function,
1372
           value_16bit );
1373
1374
          byte_stream_copy_to_uint16_little_endian(
1375
           &( sub_entry_data[ 12 ] ),
1376
           value_16bit );
1377
          libcnotify_printf(
1378
           "%s: unknown5\t\t: 0x%04" PRIx16 "\n",
1379
           function,
1380
           value_16bit );
1381
1382
          byte_stream_copy_to_uint16_little_endian(
1383
           &( sub_entry_data[ 14 ] ),
1384
           value_16bit );
1385
          libcnotify_printf(
1386
           "%s: unknown6\t\t: 0x%04" PRIx16 "\n",
1387
           function,
1388
           value_16bit );
1389
1390
          libcnotify_printf(
1391
           "\n" );
1392
        }
1393
      }
1394
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
1395
1396
568k
      total_read_count += sub_entry_data_size;
1397
568k
      file_offset      += sub_entry_data_size;
1398
568k
    }
1399
9.18k
  }
1400
29.3k
  return( total_read_count );
1401
1402
372
on_error:
1403
372
  if( internal_file_information->path != NULL )
1404
160
  {
1405
160
    memory_free(
1406
160
     internal_file_information->path );
1407
1408
160
    internal_file_information->path = NULL;
1409
160
  }
1410
372
  internal_file_information->path_size = 0;
1411
1412
372
  if( file_information_data != NULL )
1413
80
  {
1414
80
    memory_free(
1415
80
     file_information_data );
1416
80
  }
1417
372
  return( -1 );
1418
29.6k
}
1419
1420
/* Retrieves the size of the UTF-8 encoded path
1421
 * The returned size includes the end of string character
1422
 * Returns 1 if successful or -1 on error
1423
 */
1424
int libagdb_file_information_get_utf8_path_size(
1425
     libagdb_file_information_t *file_information,
1426
     size_t *utf8_string_size,
1427
     libcerror_error_t **error )
1428
0
{
1429
0
  libagdb_internal_file_information_t *internal_file_information = NULL;
1430
0
  static char *function                                          = "libagdb_file_information_get_utf8_path_size";
1431
1432
0
  if( file_information == NULL )
1433
0
  {
1434
0
    libcerror_error_set(
1435
0
     error,
1436
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1437
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1438
0
     "%s: invalid file information.",
1439
0
     function );
1440
1441
0
    return( -1 );
1442
0
  }
1443
0
  internal_file_information = (libagdb_internal_file_information_t *) file_information;
1444
1445
0
  if( libuna_utf8_string_size_from_utf16_stream(
1446
0
       internal_file_information->path,
1447
0
       internal_file_information->path_size,
1448
0
       LIBUNA_ENDIAN_LITTLE,
1449
0
       utf8_string_size,
1450
0
       error ) != 1 )
1451
0
  {
1452
0
    libcerror_error_set(
1453
0
     error,
1454
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1455
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1456
0
     "%s: unable to retrieve path UTF-8 string size.",
1457
0
     function );
1458
1459
0
    return( -1 );
1460
0
  }
1461
0
  return( 1 );
1462
0
}
1463
1464
/* Retrieves the UTF-8 encoded path
1465
 * The size should include the end of string character
1466
 * Returns 1 if successful or -1 on error
1467
 */
1468
int libagdb_file_information_get_utf8_path(
1469
     libagdb_file_information_t *file_information,
1470
     uint8_t *utf8_string,
1471
     size_t utf8_string_size,
1472
     libcerror_error_t **error )
1473
0
{
1474
0
  libagdb_internal_file_information_t *internal_file_information = NULL;
1475
0
  static char *function                                          = "libagdb_file_information_get_utf8_path";
1476
1477
0
  if( file_information == NULL )
1478
0
  {
1479
0
    libcerror_error_set(
1480
0
     error,
1481
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1482
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1483
0
     "%s: invalid file information.",
1484
0
     function );
1485
1486
0
    return( -1 );
1487
0
  }
1488
0
  internal_file_information = (libagdb_internal_file_information_t *) file_information;
1489
1490
0
  if( libuna_utf8_string_copy_from_utf16_stream(
1491
0
       utf8_string,
1492
0
       utf8_string_size,
1493
0
       internal_file_information->path,
1494
0
       internal_file_information->path_size,
1495
0
       LIBUNA_ENDIAN_LITTLE,
1496
0
       error ) != 1 )
1497
0
  {
1498
0
    libcerror_error_set(
1499
0
     error,
1500
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1501
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1502
0
     "%s: unable to copy path to UTF-8 string.",
1503
0
     function );
1504
1505
0
    return( -1 );
1506
0
  }
1507
0
  return( 1 );
1508
0
}
1509
1510
/* Retrieves the size of the UTF-16 encoded path
1511
 * The returned size includes the end of string character
1512
 * Returns 1 if successful or -1 on error
1513
 */
1514
int libagdb_file_information_get_utf16_path_size(
1515
     libagdb_file_information_t *file_information,
1516
     size_t *utf16_string_size,
1517
     libcerror_error_t **error )
1518
0
{
1519
0
  libagdb_internal_file_information_t *internal_file_information = NULL;
1520
0
  static char *function                                          = "libagdb_file_information_get_utf16_path_size";
1521
1522
0
  if( file_information == NULL )
1523
0
  {
1524
0
    libcerror_error_set(
1525
0
     error,
1526
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1527
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1528
0
     "%s: invalid file information.",
1529
0
     function );
1530
1531
0
    return( -1 );
1532
0
  }
1533
0
  internal_file_information = (libagdb_internal_file_information_t *) file_information;
1534
1535
0
  if( libuna_utf16_string_size_from_utf16_stream(
1536
0
       internal_file_information->path,
1537
0
       internal_file_information->path_size,
1538
0
       LIBUNA_ENDIAN_LITTLE,
1539
0
       utf16_string_size,
1540
0
       error ) != 1 )
1541
0
  {
1542
0
    libcerror_error_set(
1543
0
     error,
1544
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1545
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1546
0
     "%s: unable to retrieve path UTF-16 string size.",
1547
0
     function );
1548
1549
0
    return( -1 );
1550
0
  }
1551
0
  return( 1 );
1552
0
}
1553
1554
/* Retrieves the UTF-16 encoded path
1555
 * The size should include the end of string character
1556
 * Returns 1 if successful or -1 on error
1557
 */
1558
int libagdb_file_information_get_utf16_path(
1559
     libagdb_file_information_t *file_information,
1560
     uint16_t *utf16_string,
1561
     size_t utf16_string_size,
1562
     libcerror_error_t **error )
1563
0
{
1564
0
  libagdb_internal_file_information_t *internal_file_information = NULL;
1565
0
  static char *function                                          = "libagdb_file_information_get_utf16_path";
1566
1567
0
  if( file_information == NULL )
1568
0
  {
1569
0
    libcerror_error_set(
1570
0
     error,
1571
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1572
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1573
0
     "%s: invalid file information.",
1574
0
     function );
1575
1576
0
    return( -1 );
1577
0
  }
1578
0
  internal_file_information = (libagdb_internal_file_information_t *) file_information;
1579
1580
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1581
0
       utf16_string,
1582
0
       utf16_string_size,
1583
0
       internal_file_information->path,
1584
0
       internal_file_information->path_size,
1585
0
       LIBUNA_ENDIAN_LITTLE,
1586
0
       error ) != 1 )
1587
0
  {
1588
0
    libcerror_error_set(
1589
0
     error,
1590
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1591
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1592
0
     "%s: unable to copy path to UTF-16 string.",
1593
0
     function );
1594
1595
0
    return( -1 );
1596
0
  }
1597
0
  return( 1 );
1598
0
}
1599