Coverage Report

Created: 2026-07-25 07:30

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