Coverage Report

Created: 2025-06-22 07:35

/src/libvhdi/libvhdi/libvhdi_metadata_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Metadata values functions
3
 *
4
 * Copyright (C) 2012-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libvhdi_debug.h"
28
#include "libvhdi_definitions.h"
29
#include "libvhdi_libcerror.h"
30
#include "libvhdi_libcnotify.h"
31
#include "libvhdi_libfguid.h"
32
#include "libvhdi_libuna.h"
33
#include "libvhdi_metadata_item_identifier.h"
34
#include "libvhdi_metadata_table.h"
35
#include "libvhdi_metadata_table_entry.h"
36
#include "libvhdi_metadata_values.h"
37
#include "libvhdi_parent_locator.h"
38
39
/* Creates metadata values
40
 * Make sure the value metadata_values is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libvhdi_metadata_values_initialize(
44
     libvhdi_metadata_values_t **metadata_values,
45
     libcerror_error_t **error )
46
611
{
47
611
  static char *function = "libvhdi_metadata_values_initialize";
48
49
611
  if( metadata_values == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid metadata values.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
611
  if( *metadata_values != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid metadata values value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
611
  *metadata_values = memory_allocate_structure(
72
611
                     libvhdi_metadata_values_t );
73
74
611
  if( *metadata_values == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create metadata values.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
611
  if( memory_set(
86
611
       *metadata_values,
87
611
       0,
88
611
       sizeof( libvhdi_metadata_values_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear metadata values.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
611
  return( 1 );
100
101
0
on_error:
102
0
  if( *metadata_values != NULL )
103
0
  {
104
0
    memory_free(
105
0
     *metadata_values );
106
107
0
    *metadata_values = NULL;
108
0
  }
109
0
  return( -1 );
110
611
}
111
112
/* Frees metadata values
113
 * Returns 1 if successful or -1 on error
114
 */
115
int libvhdi_metadata_values_free(
116
     libvhdi_metadata_values_t **metadata_values,
117
     libcerror_error_t **error )
118
611
{
119
611
  static char *function = "libvhdi_metadata_values_free";
120
121
611
  if( metadata_values == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
127
0
     "%s: invalid metadata values.",
128
0
     function );
129
130
0
    return( -1 );
131
0
  }
132
611
  if( *metadata_values != NULL )
133
611
  {
134
611
    if( ( *metadata_values )->parent_filename != NULL )
135
0
    {
136
0
      memory_free(
137
0
       ( *metadata_values )->parent_filename );
138
0
    }
139
611
    memory_free(
140
611
     *metadata_values );
141
142
611
    *metadata_values = NULL;
143
611
  }
144
611
  return( 1 );
145
611
}
146
147
/* Reads a parent locator metadata item
148
 * Returns 1 if successful or -1 on error
149
 */
150
int libvhdi_metadata_values_read_parent_locator_item_data(
151
     libvhdi_metadata_values_t *metadata_values,
152
     const uint8_t *data,
153
     size_t data_size,
154
     libcerror_error_t **error )
155
434
{
156
434
  libvhdi_parent_locator_t *parent_locator             = NULL;
157
434
  libvhdi_parent_locator_entry_t *parent_locator_entry = NULL;
158
434
  static char *function                                = "libvhdi_metadata_values_read_parent_locator_item_data";
159
434
  int result                                           = 0;
160
161
434
  if( metadata_values == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid metadata values.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
434
  if( metadata_values->parent_filename != NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
177
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
178
0
     "%s: invalid metadata values - parent filename value already set.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
434
  if( libvhdi_parent_locator_initialize(
184
434
       &parent_locator,
185
434
       error ) != 1 )
186
0
  {
187
0
    libcerror_error_set(
188
0
     error,
189
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
190
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
191
0
     "%s: unable to create parent locator.",
192
0
     function );
193
194
0
    goto on_error;
195
0
  }
196
434
  if( libvhdi_parent_locator_read_data(
197
434
       parent_locator,
198
434
       data,
199
434
       data_size,
200
434
       error ) != 1 )
201
172
  {
202
172
    libcerror_error_set(
203
172
     error,
204
172
     LIBCERROR_ERROR_DOMAIN_IO,
205
172
     LIBCERROR_IO_ERROR_READ_FAILED,
206
172
     "%s: unable to read parent locator.",
207
172
     function );
208
209
172
    goto on_error;
210
172
  }
211
262
  result = libvhdi_parent_locator_get_entry_by_utf8_key(
212
262
            parent_locator,
213
262
            (uint8_t *) "parent_linkage",
214
262
            14,
215
262
            &parent_locator_entry,
216
262
            error );
217
218
262
  if( result == -1 )
219
37
  {
220
37
    libcerror_error_set(
221
37
     error,
222
37
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
223
37
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
224
37
     "%s: unable to retrieve parent linkage entry.",
225
37
     function );
226
227
37
    goto on_error;
228
37
  }
229
225
  else if( result != 0 )
230
0
  {
231
0
    if( libvhdi_parent_locator_get_value_as_guid(
232
0
         parent_locator_entry,
233
0
         metadata_values->parent_identifier,
234
0
         16,
235
0
         error ) != 1 )
236
0
    {
237
0
      libcerror_error_set(
238
0
       error,
239
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
240
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
241
0
       "%s: unable to retrieve parent linkage value as big-endian GUID.",
242
0
       function );
243
244
0
      goto on_error;
245
0
    }
246
0
  }
247
225
  result = libvhdi_parent_locator_get_entry_by_utf8_key(
248
225
            parent_locator,
249
225
            (uint8_t *) "absolute_win32_path",
250
225
            19,
251
225
            &parent_locator_entry,
252
225
            error );
253
254
225
  if( result == -1 )
255
4
  {
256
4
    libcerror_error_set(
257
4
     error,
258
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
259
4
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
260
4
     "%s: unable to retrieve absolute WIN32 path entry.",
261
4
     function );
262
263
4
    goto on_error;
264
4
  }
265
221
  if( result == 0 )
266
221
  {
267
221
    result = libvhdi_parent_locator_get_entry_by_utf8_key(
268
221
              parent_locator,
269
221
              (uint8_t *) "volume_path",
270
221
              11,
271
221
              &parent_locator_entry,
272
221
              error );
273
274
221
    if( result == -1 )
275
5
    {
276
5
      libcerror_error_set(
277
5
       error,
278
5
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
279
5
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
280
5
       "%s: unable to retrieve volume path entry.",
281
5
       function );
282
283
5
      goto on_error;
284
5
    }
285
221
  }
286
216
  if( result == 0 )
287
216
  {
288
216
    result = libvhdi_parent_locator_get_entry_by_utf8_key(
289
216
              parent_locator,
290
216
              (uint8_t *) "relative_path",
291
216
              12,
292
216
              &parent_locator_entry,
293
216
              error );
294
295
216
    if( result == -1 )
296
1
    {
297
1
      libcerror_error_set(
298
1
       error,
299
1
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
300
1
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
301
1
       "%s: unable to retrieve volume path entry.",
302
1
       function );
303
304
1
      goto on_error;
305
1
    }
306
216
  }
307
215
  if( result != 0 )
308
0
  {
309
0
    if( parent_locator_entry == NULL )
310
0
    {
311
0
      libcerror_error_set(
312
0
       error,
313
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
314
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
315
0
       "%s: missing path entry.",
316
0
       function );
317
318
0
      goto on_error;
319
0
    }
320
0
    metadata_values->parent_filename      = parent_locator_entry->value_data;
321
0
    metadata_values->parent_filename_size = parent_locator_entry->value_data_size;
322
323
0
    parent_locator_entry->value_data      = NULL;
324
0
    parent_locator_entry->value_data_size = 0;
325
0
  }
326
215
  if( libvhdi_parent_locator_free(
327
215
       &parent_locator,
328
215
       error ) != 1 )
329
0
  {
330
0
    libcerror_error_set(
331
0
     error,
332
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
334
0
     "%s: unable to free parent locator.",
335
0
     function );
336
337
0
    goto on_error;
338
0
  }
339
215
  return( 1 );
340
341
219
on_error:
342
219
  if( parent_locator != NULL )
343
219
  {
344
219
    libvhdi_parent_locator_free(
345
219
     &parent_locator,
346
219
     NULL );
347
219
  }
348
219
  if( metadata_values->parent_filename != NULL )
349
0
  {
350
0
    memory_free(
351
0
     metadata_values->parent_filename );
352
353
0
    metadata_values->parent_filename = NULL;
354
0
  }
355
219
  metadata_values->parent_filename_size = 0;
356
357
219
  return( -1 );
358
215
}
359
360
/* Reads a metadata item
361
 * Returns 1 if successful or -1 on error
362
 */
363
int libvhdi_metadata_values_read_item_data(
364
     libvhdi_metadata_values_t *metadata_values,
365
     libvhdi_metadata_table_entry_t *metadata_table_entry,
366
     const uint8_t *data,
367
     size_t data_size,
368
     libcerror_error_t **error )
369
1.26k
{
370
1.26k
  static char *function          = "libvhdi_metadata_values_read_item_data";
371
1.26k
  uint32_t file_parameters_flags = 0;
372
373
1.26k
  if( metadata_values == NULL )
374
0
  {
375
0
    libcerror_error_set(
376
0
     error,
377
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
378
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
379
0
     "%s: invalid metadata values.",
380
0
     function );
381
382
0
    return( -1 );
383
0
  }
384
1.26k
  if( metadata_table_entry == NULL )
385
0
  {
386
0
    libcerror_error_set(
387
0
     error,
388
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
389
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
390
0
     "%s: invalid metadata table entry.",
391
0
     function );
392
393
0
    return( -1 );
394
0
  }
395
1.26k
  if( data == NULL )
396
0
  {
397
0
    libcerror_error_set(
398
0
     error,
399
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
400
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
401
0
     "%s: invalid data.",
402
0
     function );
403
404
0
    return( -1 );
405
0
  }
406
1.26k
  if( ( data_size == 0 )
407
1.26k
   || ( data_size > (size_t) SSIZE_MAX ) )
408
0
  {
409
0
    libcerror_error_set(
410
0
     error,
411
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
413
0
     "%s: invalid data size value out of bounds.",
414
0
     function );
415
416
0
    return( -1 );
417
0
  }
418
#if defined( HAVE_DEBUG_OUTPUT )
419
  if( libcnotify_verbose != 0 )
420
  {
421
    if( libvhdi_debug_print_guid_value(
422
         function,
423
         "metadata item identifier\t",
424
         metadata_table_entry->item_identifier,
425
         16,
426
         LIBFGUID_ENDIAN_LITTLE,
427
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
428
         error ) != 1 )
429
    {
430
      libcerror_error_set(
431
       error,
432
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
433
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
434
       "%s: unable to print GUID value.",
435
       function );
436
437
      goto on_error;
438
    }
439
    libcnotify_printf(
440
     "%s: metadata item description\t: %s\n",
441
     function,
442
     libvhdi_metadata_item_identifier_get_description(
443
      metadata_table_entry->item_identifier ) );
444
445
    libcnotify_printf(
446
     "%s: metadata item data:\n",
447
     function );
448
    libcnotify_print_data(
449
     data,
450
     (size_t) metadata_table_entry->item_size,
451
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
452
  }
453
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
454
455
1.26k
  if( memory_compare(
456
1.26k
       metadata_table_entry->item_identifier,
457
1.26k
       libvhdi_metadata_item_identifier_file_parameters,
458
1.26k
       16 ) == 0 )
459
77
  {
460
77
    if( metadata_table_entry->item_size != 8 )
461
21
    {
462
21
      libcerror_error_set(
463
21
       error,
464
21
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
465
21
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
466
21
       "%s: unsupported file parameters size item data size.",
467
21
       function );
468
469
21
      goto on_error;
470
21
    }
471
56
    byte_stream_copy_to_uint32_little_endian(
472
56
     data,
473
56
     metadata_values->block_size );
474
475
56
    byte_stream_copy_to_uint32_little_endian(
476
56
     &( data[ 4 ] ),
477
56
     file_parameters_flags );
478
479
#if defined( HAVE_DEBUG_OUTPUT )
480
    if( libcnotify_verbose != 0 )
481
    {
482
      libcnotify_printf(
483
       "%s: block size\t\t\t: %" PRIu32 "\n",
484
       function,
485
       metadata_values->block_size );
486
487
      libcnotify_printf(
488
       "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n",
489
       function,
490
       file_parameters_flags );
491
    }
492
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
493
494
56
    if( ( metadata_values->block_size < ( 1024 * 1024 ) )
495
56
     || ( metadata_values->block_size > ( 256 * 1024 * 1024 ) ) )
496
14
    {
497
14
      libcerror_error_set(
498
14
       error,
499
14
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
500
14
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
501
14
       "%s: invalid block size value out of bounds.",
502
14
       function );
503
504
14
      goto on_error;
505
14
    }
506
/* TODO check if block size is power of 2 */
507
42
    if( ( metadata_values->block_size % 512 ) != 0 )
508
16
    {
509
16
      libcerror_error_set(
510
16
       error,
511
16
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
16
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
513
16
       "%s: unsupported block size: %" PRIu32 ".",
514
16
       function,
515
16
       metadata_values->block_size );
516
517
16
      goto on_error;
518
16
    }
519
26
    file_parameters_flags &= 0x00000003UL;
520
521
26
    switch( file_parameters_flags )
522
26
    {
523
12
      case 0:
524
12
        metadata_values->disk_type = LIBVHDI_DISK_TYPE_DYNAMIC;
525
12
        break;
526
527
5
      case 1:
528
5
        metadata_values->disk_type = LIBVHDI_DISK_TYPE_FIXED;
529
5
        break;
530
531
8
      case 2:
532
8
        metadata_values->disk_type = LIBVHDI_DISK_TYPE_DIFFERENTIAL;
533
8
        break;
534
535
1
      default:
536
1
        libcerror_error_set(
537
1
         error,
538
1
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
539
1
         LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
540
1
         "%s: unsupported file parameters flags: 0x%02" PRIx32 ".",
541
1
         function,
542
1
         file_parameters_flags );
543
544
1
        goto on_error;
545
26
    }
546
26
  }
547
1.19k
  else if( memory_compare(
548
1.19k
            metadata_table_entry->item_identifier,
549
1.19k
            libvhdi_metadata_item_identifier_logical_sector_size,
550
1.19k
            16 ) == 0 )
551
60
  {
552
60
    if( metadata_table_entry->item_size != 4 )
553
20
    {
554
20
      libcerror_error_set(
555
20
       error,
556
20
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
557
20
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
558
20
       "%s: unsupported logical sector size item data size.",
559
20
       function );
560
561
20
      goto on_error;
562
20
    }
563
40
    byte_stream_copy_to_uint32_little_endian(
564
40
     data,
565
40
     metadata_values->logical_sector_size );
566
567
#if defined( HAVE_DEBUG_OUTPUT )
568
    if( libcnotify_verbose != 0 )
569
    {
570
      libcnotify_printf(
571
       "%s: logical sector size\t\t: %" PRIu32 "\n",
572
       function,
573
       metadata_values->logical_sector_size );
574
    }
575
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
576
577
40
    if( ( metadata_values->logical_sector_size != 512 )
578
40
     && ( metadata_values->logical_sector_size != 4096 ) )
579
37
    {
580
37
      libcerror_error_set(
581
37
       error,
582
37
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
583
37
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
584
37
       "%s: invalid logical sector size value out of bounds.",
585
37
       function );
586
587
37
      goto on_error;
588
37
    }
589
40
  }
590
1.13k
  else if( memory_compare(
591
1.13k
            metadata_table_entry->item_identifier,
592
1.13k
            libvhdi_metadata_item_identifier_parent_locator,
593
1.13k
            16 ) == 0 )
594
434
  {
595
434
    if( libvhdi_metadata_values_read_parent_locator_item_data(
596
434
         metadata_values,
597
434
         data,
598
434
         (size_t) metadata_table_entry->item_size,
599
434
         error ) != 1 )
600
219
    {
601
219
      libcerror_error_set(
602
219
       error,
603
219
       LIBCERROR_ERROR_DOMAIN_IO,
604
219
       LIBCERROR_IO_ERROR_READ_FAILED,
605
219
       "%s: unable to read parent locator metadata item.",
606
219
       function );
607
608
219
      goto on_error;
609
219
    }
610
434
  }
611
698
  else if( memory_compare(
612
698
            metadata_table_entry->item_identifier,
613
698
            libvhdi_metadata_item_identifier_physical_sector_size,
614
698
            16 ) == 0 )
615
67
  {
616
67
    if( metadata_table_entry->item_size != 4 )
617
20
    {
618
20
      libcerror_error_set(
619
20
       error,
620
20
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
621
20
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
622
20
       "%s: unsupported physical sector size item data size.",
623
20
       function );
624
625
20
      goto on_error;
626
20
    }
627
47
    byte_stream_copy_to_uint32_little_endian(
628
47
     data,
629
47
     metadata_values->physical_sector_size );
630
631
#if defined( HAVE_DEBUG_OUTPUT )
632
    if( libcnotify_verbose != 0 )
633
    {
634
      libcnotify_printf(
635
       "%s: physical sector size\t\t: %" PRIu32 "\n",
636
       function,
637
       metadata_values->physical_sector_size );
638
    }
639
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
640
641
47
    if( ( metadata_values->physical_sector_size != 512 )
642
47
     && ( metadata_values->physical_sector_size != 4096 ) )
643
45
    {
644
45
      libcerror_error_set(
645
45
       error,
646
45
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
647
45
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
648
45
       "%s: invalid physical sector size value out of bounds.",
649
45
       function );
650
651
45
      goto on_error;
652
45
    }
653
47
  }
654
631
  else if( memory_compare(
655
631
            metadata_table_entry->item_identifier,
656
631
            libvhdi_metadata_item_identifier_virtual_disk_identifier,
657
631
            16 ) == 0 )
658
24
  {
659
24
    if( metadata_table_entry->item_size != 16 )
660
17
    {
661
17
      libcerror_error_set(
662
17
       error,
663
17
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
664
17
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
665
17
       "%s: unsupported virtual disk identifier item data size.",
666
17
       function );
667
668
17
      goto on_error;
669
17
    }
670
7
    metadata_values->virtual_disk_identifier[ 0 ] = data[ 3 ];
671
7
    metadata_values->virtual_disk_identifier[ 1 ] = data[ 2 ];
672
7
    metadata_values->virtual_disk_identifier[ 2 ] = data[ 1 ];
673
7
    metadata_values->virtual_disk_identifier[ 3 ] = data[ 0 ];
674
675
7
    metadata_values->virtual_disk_identifier[ 4 ] = data[ 5 ];
676
7
    metadata_values->virtual_disk_identifier[ 5 ] = data[ 4 ];
677
678
7
    metadata_values->virtual_disk_identifier[ 6 ] = data[ 7 ];
679
7
    metadata_values->virtual_disk_identifier[ 7 ] = data[ 6 ];
680
681
7
    if( memory_copy(
682
7
         &( metadata_values->virtual_disk_identifier[ 8 ] ),
683
7
         &( data[ 8 ] ),
684
7
         8 ) == NULL )
685
0
    {
686
0
      libcerror_error_set(
687
0
       error,
688
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
689
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
690
0
       "%s: unable to copy virtual disk identifier.",
691
0
       function );
692
693
0
      goto on_error;
694
0
    }
695
#if defined( HAVE_DEBUG_OUTPUT )
696
    if( libcnotify_verbose != 0 )
697
    {
698
      if( libvhdi_debug_print_guid_value(
699
           function,
700
           "virtual disk identifier\t\t",
701
           metadata_values->virtual_disk_identifier,
702
           16,
703
           LIBFGUID_ENDIAN_BIG,
704
           LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
705
           error ) != 1 )
706
      {
707
        libcerror_error_set(
708
         error,
709
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
710
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
711
         "%s: unable to print GUID value.",
712
         function );
713
714
        goto on_error;
715
      }
716
    }
717
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
718
7
  }
719
607
  else if( memory_compare(
720
607
            metadata_table_entry->item_identifier,
721
607
            libvhdi_metadata_item_identifier_virtual_disk_size,
722
607
            16 ) == 0 )
723
28
  {
724
28
    if( metadata_table_entry->item_size != 8 )
725
20
    {
726
20
      libcerror_error_set(
727
20
       error,
728
20
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
20
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
730
20
       "%s: unsupported virtual disk size item data size.",
731
20
       function );
732
733
20
      goto on_error;
734
20
    }
735
8
    byte_stream_copy_to_uint64_little_endian(
736
8
     data,
737
8
     metadata_values->virtual_disk_size );
738
739
#if defined( HAVE_DEBUG_OUTPUT )
740
    if( libcnotify_verbose != 0 )
741
    {
742
      libcnotify_printf(
743
       "%s: virtual disk size\t\t: %" PRIu64 "\n",
744
       function,
745
       metadata_values->virtual_disk_size );
746
    }
747
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
748
8
  }
749
#if defined( HAVE_DEBUG_OUTPUT )
750
  if( libcnotify_verbose != 0 )
751
  {
752
    libcnotify_printf(
753
     "\n" );
754
  }
755
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
756
757
839
  return( 1 );
758
759
430
on_error:
760
430
  if( metadata_values->parent_filename != NULL )
761
0
  {
762
0
    memory_free(
763
0
     metadata_values->parent_filename );
764
765
0
    metadata_values->parent_filename = NULL;
766
0
  }
767
430
  metadata_values->parent_filename_size = 0;
768
769
430
  return( -1 );
770
1.26k
}
771
772
/* Reads a metadata item
773
 * Returns 1 if successful or -1 on error
774
 */
775
int libvhdi_metadata_values_read_item_file_io_handle(
776
     libvhdi_metadata_values_t *metadata_values,
777
     libvhdi_metadata_table_entry_t *metadata_table_entry,
778
     libbfio_handle_t *file_io_handle,
779
     off64_t metadata_region_offset,
780
     libcerror_error_t **error )
781
1.38k
{
782
1.38k
  uint8_t *data                = NULL;
783
1.38k
  static char *function        = "libvhdi_metadata_values_read_item_file_io_handle";
784
1.38k
  ssize_t read_count           = 0;
785
1.38k
  off64_t metadata_item_offset = 0;
786
787
1.38k
  if( metadata_values == NULL )
788
0
  {
789
0
    libcerror_error_set(
790
0
     error,
791
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
792
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
793
0
     "%s: invalid metadata values.",
794
0
     function );
795
796
0
    return( -1 );
797
0
  }
798
1.38k
  if( metadata_table_entry == NULL )
799
0
  {
800
0
    libcerror_error_set(
801
0
     error,
802
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
803
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
804
0
     "%s: invalid metadata table entry.",
805
0
     function );
806
807
0
    return( -1 );
808
0
  }
809
1.38k
  metadata_item_offset = metadata_region_offset + metadata_table_entry->item_offset;
810
811
1.38k
  if( ( metadata_table_entry->item_size == 0 )
812
1.38k
   || ( metadata_table_entry->item_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
813
43
  {
814
43
    libcerror_error_set(
815
43
     error,
816
43
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
817
43
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
818
43
     "%s: invalid metadate table entry - item data size value out of bounds.",
819
43
     function );
820
821
43
    goto on_error;
822
43
  }
823
#if defined( HAVE_DEBUG_OUTPUT )
824
  if( libcnotify_verbose != 0 )
825
  {
826
    libcnotify_printf(
827
     "%s: reading metadata item at offset: %" PRIi64 " (0x%08" PRIx64 ").\n",
828
     function,
829
     metadata_item_offset,
830
     metadata_item_offset );
831
  }
832
#endif
833
1.34k
  data = (uint8_t *) memory_allocate(
834
1.34k
                      sizeof( uint8_t ) * metadata_table_entry->item_size );
835
836
1.34k
  if( data == NULL )
837
0
  {
838
0
    libcerror_error_set(
839
0
     error,
840
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
841
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
842
0
     "%s: unable to create metadata item data.",
843
0
     function );
844
845
0
    goto on_error;
846
0
  }
847
1.34k
  read_count = libbfio_handle_read_buffer_at_offset(
848
1.34k
                file_io_handle,
849
1.34k
                data,
850
1.34k
                (size_t) metadata_table_entry->item_size,
851
1.34k
                metadata_item_offset,
852
1.34k
                error );
853
854
1.34k
  if( read_count != (ssize_t) (size_t) metadata_table_entry->item_size )
855
71
  {
856
71
    libcerror_error_set(
857
71
     error,
858
71
     LIBCERROR_ERROR_DOMAIN_IO,
859
71
     LIBCERROR_IO_ERROR_READ_FAILED,
860
71
     "%s: unable to read metadata item data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
861
71
     function,
862
71
     metadata_item_offset,
863
71
     metadata_item_offset );
864
865
71
    goto on_error;
866
71
  }
867
1.26k
  if( libvhdi_metadata_values_read_item_data(
868
1.26k
       metadata_values,
869
1.26k
       metadata_table_entry,
870
1.26k
       data,
871
1.26k
       (size_t) metadata_table_entry->item_size,
872
1.26k
       error ) != 1 )
873
430
  {
874
430
    libcerror_error_set(
875
430
     error,
876
430
     LIBCERROR_ERROR_DOMAIN_IO,
877
430
     LIBCERROR_IO_ERROR_READ_FAILED,
878
430
     "%s: unable to read metadata item.",
879
430
     function );
880
881
430
    goto on_error;
882
430
  }
883
839
  memory_free(
884
839
   data );
885
886
839
  return( 1 );
887
888
544
on_error:
889
544
  if( data != NULL )
890
501
  {
891
501
    memory_free(
892
501
     data );
893
501
  }
894
544
  return( -1 );
895
1.26k
}
896
897
/* Reads the metadata values
898
 * Returns 1 if successful or -1 on error
899
 */
900
int libvhdi_metadata_values_read_file_io_handle(
901
     libvhdi_metadata_values_t *metadata_values,
902
     libbfio_handle_t *file_io_handle,
903
     off64_t metadata_region_offset,
904
     libcerror_error_t **error )
905
611
{
906
611
  libvhdi_metadata_table_t *metadata_table = NULL;
907
611
  libvhdi_metadata_table_entry_t *entry    = NULL;
908
611
  static char *function                    = "libvhdi_metadata_values_read_file_io_handle";
909
611
  int entry_index                          = 0;
910
611
  int number_of_entries                    = 0;
911
912
611
  if( metadata_values == NULL )
913
0
  {
914
0
    libcerror_error_set(
915
0
     error,
916
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
917
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
918
0
     "%s: invalid metadata values.",
919
0
     function );
920
921
0
    return( -1 );
922
0
  }
923
611
  if( libvhdi_metadata_table_initialize(
924
611
       &metadata_table,
925
611
       error ) != 1 )
926
0
  {
927
0
    libcerror_error_set(
928
0
     error,
929
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
930
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
931
0
     "%s: unable to create metadata table.",
932
0
     function );
933
934
0
    goto on_error;
935
0
  }
936
611
  if( libvhdi_metadata_table_read_file_io_handle(
937
611
       metadata_table,
938
611
       file_io_handle,
939
611
       metadata_region_offset,
940
611
       error ) != 1 )
941
57
  {
942
57
    libcerror_error_set(
943
57
     error,
944
57
     LIBCERROR_ERROR_DOMAIN_IO,
945
57
     LIBCERROR_IO_ERROR_READ_FAILED,
946
57
     "%s: unable to read metadata table.",
947
57
     function );
948
949
57
    goto on_error;
950
57
  }
951
554
  if( libvhdi_metadata_table_get_number_of_entries(
952
554
       metadata_table,
953
554
       &number_of_entries,
954
554
       error ) != 1 )
955
0
  {
956
0
    libcerror_error_set(
957
0
     error,
958
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
959
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
960
0
     "%s: unable to retrieve number of entries from metadata table.",
961
0
     function );
962
963
0
    goto on_error;
964
0
  }
965
554
  for( entry_index = 0;
966
1.39k
       entry_index < number_of_entries;
967
839
       entry_index++ )
968
1.38k
  {
969
1.38k
    if( libvhdi_metadata_table_get_entry_by_index(
970
1.38k
         metadata_table,
971
1.38k
         entry_index,
972
1.38k
         &entry,
973
1.38k
         error ) != 1 )
974
0
    {
975
0
      libcerror_error_set(
976
0
       error,
977
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
978
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
979
0
       "%s: unable to retrieve entry: %d from metadata table.",
980
0
       function,
981
0
       entry_index );
982
983
0
      goto on_error;
984
0
    }
985
1.38k
    if( entry == NULL )
986
0
    {
987
0
      libcerror_error_set(
988
0
       error,
989
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
990
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
991
0
       "%s: missing entry: %d.",
992
0
       function,
993
0
       entry_index );
994
995
0
      goto on_error;
996
0
    }
997
1.38k
    if( libvhdi_metadata_values_read_item_file_io_handle(
998
1.38k
         metadata_values,
999
1.38k
         entry,
1000
1.38k
         file_io_handle,
1001
1.38k
         metadata_region_offset,
1002
1.38k
         error ) != 1 )
1003
544
    {
1004
544
      libcerror_error_set(
1005
544
       error,
1006
544
       LIBCERROR_ERROR_DOMAIN_IO,
1007
544
       LIBCERROR_IO_ERROR_READ_FAILED,
1008
544
       "%s: unable to read metadata item: %d.",
1009
544
       function,
1010
544
       entry_index );
1011
1012
544
      goto on_error;
1013
544
    }
1014
1.38k
  }
1015
10
  if( libvhdi_metadata_table_free(
1016
10
       &metadata_table,
1017
10
       error ) != 1 )
1018
0
  {
1019
0
    libcerror_error_set(
1020
0
     error,
1021
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1022
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1023
0
     "%s: unable to free metadata table.",
1024
0
     function );
1025
1026
0
    goto on_error;
1027
0
  }
1028
10
  return( 1 );
1029
1030
601
on_error:
1031
601
  if( metadata_table != NULL )
1032
601
  {
1033
601
    libvhdi_metadata_table_free(
1034
601
     &metadata_table,
1035
601
     NULL );
1036
601
  }
1037
601
  return( -1 );
1038
10
}
1039
1040
/* Retrieves the virtual disk identifier
1041
 * The identifier is a big-endian GUID and is 16 bytes of size
1042
 * Returns 1 if successful or -1 on error
1043
 */
1044
int libvhdi_metadata_values_get_virtual_disk_identifier(
1045
     libvhdi_metadata_values_t *metadata_values,
1046
     uint8_t *guid_data,
1047
     size_t guid_data_size,
1048
     libcerror_error_t **error )
1049
0
{
1050
0
  static char *function = "libvhdi_metadata_values_get_virtual_disk_identifier";
1051
1052
0
  if( metadata_values == NULL )
1053
0
  {
1054
0
    libcerror_error_set(
1055
0
     error,
1056
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1057
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1058
0
     "%s: invalid metadata values.",
1059
0
     function );
1060
1061
0
    return( -1 );
1062
0
  }
1063
0
  if( guid_data == NULL )
1064
0
  {
1065
0
    libcerror_error_set(
1066
0
     error,
1067
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1068
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1069
0
     "%s: invalid GUID data.",
1070
0
     function );
1071
1072
0
    return( -1 );
1073
0
  }
1074
0
  if( ( guid_data_size < 16 )
1075
0
   || ( guid_data_size > SSIZE_MAX ) )
1076
0
  {
1077
0
    libcerror_error_set(
1078
0
     error,
1079
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1080
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1081
0
     "%s: invalid GUID data size value out of bounds.",
1082
0
     function );
1083
1084
0
    return( -1 );
1085
0
  }
1086
0
  if( memory_copy(
1087
0
       guid_data,
1088
0
       metadata_values->virtual_disk_identifier,
1089
0
       16 ) == NULL )
1090
0
  {
1091
0
    libcerror_error_set(
1092
0
     error,
1093
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1094
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1095
0
     "%s: unable to copy virtual disk identifier.",
1096
0
     function );
1097
1098
0
    return( -1 );
1099
0
  }
1100
0
  return( 1 );
1101
0
}
1102
1103
/* Retrieves the parent identifier
1104
 * The identifier is a big-endian GUID and is 16 bytes of size
1105
 * Returns 1 if successful or -1 on error
1106
 */
1107
int libvhdi_metadata_values_get_parent_identifier(
1108
     libvhdi_metadata_values_t *metadata_values,
1109
     uint8_t *guid_data,
1110
     size_t guid_data_size,
1111
     libcerror_error_t **error )
1112
0
{
1113
0
  static char *function = "libvhdi_metadata_values_get_parent_identifier";
1114
1115
0
  if( metadata_values == NULL )
1116
0
  {
1117
0
    libcerror_error_set(
1118
0
     error,
1119
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1120
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1121
0
     "%s: invalid metadata values.",
1122
0
     function );
1123
1124
0
    return( -1 );
1125
0
  }
1126
0
  if( guid_data == 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 GUID data.",
1133
0
     function );
1134
1135
0
    return( -1 );
1136
0
  }
1137
0
  if( ( guid_data_size < 16 )
1138
0
   || ( guid_data_size > SSIZE_MAX ) )
1139
0
  {
1140
0
    libcerror_error_set(
1141
0
     error,
1142
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1143
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1144
0
     "%s: invalid GUID data size value out of bounds.",
1145
0
     function );
1146
1147
0
    return( -1 );
1148
0
  }
1149
0
  if( memory_copy(
1150
0
       guid_data,
1151
0
       metadata_values->parent_identifier,
1152
0
       16 ) == NULL )
1153
0
  {
1154
0
    libcerror_error_set(
1155
0
     error,
1156
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1157
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1158
0
     "%s: unable to copy parent identifier.",
1159
0
     function );
1160
1161
0
    return( -1 );
1162
0
  }
1163
0
  return( 1 );
1164
0
}
1165
1166
/* Retrieves the size of the UTF-8 encoded parent filename
1167
 * The returned size includes the end of string character
1168
 * Returns 1 if successful, 0 if not available or -1 on error
1169
 */
1170
int libvhdi_metadata_values_get_utf8_parent_filename_size(
1171
     libvhdi_metadata_values_t *metadata_values,
1172
     size_t *utf8_string_size,
1173
     libcerror_error_t **error )
1174
0
{
1175
0
  static char *function = "libvhdi_metadata_values_get_utf8_parent_filename_size";
1176
0
  int result            = 0;
1177
1178
0
  if( metadata_values == NULL )
1179
0
  {
1180
0
    libcerror_error_set(
1181
0
     error,
1182
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1183
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1184
0
     "%s: invalid dynamic disk header.",
1185
0
     function );
1186
1187
0
    return( -1 );
1188
0
  }
1189
0
  if( ( metadata_values->parent_filename != NULL )
1190
0
   && ( metadata_values->parent_filename_size > 0 ) )
1191
0
  {
1192
0
    result = libuna_utf8_string_size_from_utf16_stream(
1193
0
              metadata_values->parent_filename,
1194
0
              metadata_values->parent_filename_size,
1195
0
              LIBUNA_ENDIAN_LITTLE,
1196
0
              utf8_string_size,
1197
0
              error );
1198
1199
0
    if( result != 1 )
1200
0
    {
1201
0
      libcerror_error_set(
1202
0
       error,
1203
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1204
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1205
0
       "%s: unable to retrieve UTF-8 string size.",
1206
0
       function );
1207
1208
0
      return( -1 );
1209
0
    }
1210
0
  }
1211
0
  return( result );
1212
0
}
1213
1214
/* Retrieves the UTF-8 encoded parent filename
1215
 * The size should include the end of string character
1216
 * Returns 1 if successful, 0 if not available or -1 on error
1217
 */
1218
int libvhdi_metadata_values_get_utf8_parent_filename(
1219
     libvhdi_metadata_values_t *metadata_values,
1220
     uint8_t *utf8_string,
1221
     size_t utf8_string_size,
1222
     libcerror_error_t **error )
1223
0
{
1224
0
  static char *function = "libvhdi_metadata_values_get_utf8_parent_filename";
1225
0
  int result            = 0;
1226
1227
0
  if( metadata_values == NULL )
1228
0
  {
1229
0
    libcerror_error_set(
1230
0
     error,
1231
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1232
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1233
0
     "%s: invalid dynamic disk header.",
1234
0
     function );
1235
1236
0
    return( -1 );
1237
0
  }
1238
0
  if( ( metadata_values->parent_filename != NULL )
1239
0
   && ( metadata_values->parent_filename_size > 0 ) )
1240
0
  {
1241
0
    result = libuna_utf8_string_copy_from_utf16_stream(
1242
0
              utf8_string,
1243
0
              utf8_string_size,
1244
0
              metadata_values->parent_filename,
1245
0
              metadata_values->parent_filename_size,
1246
0
              LIBUNA_ENDIAN_LITTLE,
1247
0
              error );
1248
1249
0
    if( result != 1 )
1250
0
    {
1251
0
      libcerror_error_set(
1252
0
       error,
1253
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1254
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1255
0
       "%s: unable to copy parent filename to UTF-8 string.",
1256
0
       function );
1257
1258
0
      return( -1 );
1259
0
    }
1260
0
  }
1261
0
  return( result );
1262
0
}
1263
1264
/* Retrieves the size of the UTF-16 encoded parent filename
1265
 * The returned size includes the end of string character
1266
 * Returns 1 if successful, 0 if not available or -1 on error
1267
 */
1268
int libvhdi_metadata_values_get_utf16_parent_filename_size(
1269
     libvhdi_metadata_values_t *metadata_values,
1270
     size_t *utf16_string_size,
1271
     libcerror_error_t **error )
1272
0
{
1273
0
  static char *function = "libvhdi_metadata_values_get_utf16_parent_filename_size";
1274
0
  int result            = 0;
1275
1276
0
  if( metadata_values == NULL )
1277
0
  {
1278
0
    libcerror_error_set(
1279
0
     error,
1280
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1281
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1282
0
     "%s: invalid dynamic disk header.",
1283
0
     function );
1284
1285
0
    return( -1 );
1286
0
  }
1287
0
  if( ( metadata_values->parent_filename != NULL )
1288
0
   && ( metadata_values->parent_filename_size > 0 ) )
1289
0
  {
1290
0
    result = libuna_utf16_string_size_from_utf16_stream(
1291
0
              metadata_values->parent_filename,
1292
0
              metadata_values->parent_filename_size,
1293
0
              LIBUNA_ENDIAN_LITTLE,
1294
0
              utf16_string_size,
1295
0
              error );
1296
1297
0
    if( result != 1 )
1298
0
    {
1299
0
      libcerror_error_set(
1300
0
       error,
1301
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1302
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1303
0
       "%s: unable to retrieve UTF-16 string size.",
1304
0
       function );
1305
1306
0
      return( -1 );
1307
0
    }
1308
0
  }
1309
0
  return( result );
1310
0
}
1311
1312
/* Retrieves the UTF-16 encoded parent filename
1313
 * The size should include the end of string character
1314
 * Returns 1 if successful, 0 if not available or -1 on error
1315
 */
1316
int libvhdi_metadata_values_get_utf16_parent_filename(
1317
     libvhdi_metadata_values_t *metadata_values,
1318
     uint16_t *utf16_string,
1319
     size_t utf16_string_size,
1320
     libcerror_error_t **error )
1321
0
{
1322
0
  static char *function = "libvhdi_metadata_values_get_utf16_parent_filename";
1323
0
  int result            = 0;
1324
1325
0
  if( metadata_values == NULL )
1326
0
  {
1327
0
    libcerror_error_set(
1328
0
     error,
1329
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1330
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1331
0
     "%s: invalid dynamic disk header.",
1332
0
     function );
1333
1334
0
    return( -1 );
1335
0
  }
1336
0
  if( ( metadata_values->parent_filename != NULL )
1337
0
   && ( metadata_values->parent_filename_size > 0 ) )
1338
0
  {
1339
0
    result = libuna_utf16_string_copy_from_utf16_stream(
1340
0
              utf16_string,
1341
0
              utf16_string_size,
1342
0
              metadata_values->parent_filename,
1343
0
              metadata_values->parent_filename_size,
1344
0
              LIBUNA_ENDIAN_LITTLE,
1345
0
              error );
1346
1347
0
    if( result != 1 )
1348
0
    {
1349
0
      libcerror_error_set(
1350
0
       error,
1351
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1352
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1353
0
       "%s: unable to copy parent filename to UTF-16 string.",
1354
0
       function );
1355
1356
0
      return( -1 );
1357
0
    }
1358
0
  }
1359
0
  return( result );
1360
0
}
1361