Coverage Report

Created: 2026-01-20 07:11

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