Coverage Report

Created: 2024-10-02 06:58

/src/libewf/libewf/libewf_device_information.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Device information functions
3
 *
4
 * Copyright (C) 2006-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 <memory.h>
24
#include <types.h>
25
26
#include "libewf_definitions.h"
27
#include "libewf_device_information.h"
28
#include "libewf_header_values.h"
29
#include "libewf_libcerror.h"
30
#include "libewf_libcnotify.h"
31
#include "libewf_libfvalue.h"
32
#include "libewf_libuna.h"
33
#include "libewf_media_values.h"
34
#include "libewf_value_table.h"
35
36
/* Generate an UTF-8 encoded device information string
37
 * Sets utf8_string and utf8_string_size
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libewf_device_information_generate_utf8_string(
41
     uint8_t **utf8_string,
42
     size_t *utf8_string_size,
43
     libewf_media_values_t *media_values,
44
     libfvalue_table_t *header_values,
45
     libcerror_error_t **error )
46
0
{
47
0
  uint8_t *safe_utf8_string               = NULL;
48
0
  static char *function                   = "libewf_device_information_generate_utf8_string";
49
0
  const char *newline_string              = "\n";
50
0
  size_t bytes_per_sector_string_length   = 0;
51
0
  size_t device_label_string_length       = 0;
52
0
  size_t model_string_length              = 0;
53
0
  size_t newline_string_length            = 1;
54
0
  size_t number_of_sectors_string_length  = 0;
55
0
  size_t process_identifier_string_length = 0;
56
0
  size_t safe_utf8_string_size            = 0;
57
0
  size_t serial_number_string_length      = 0;
58
0
  size_t utf8_string_index                = 0;
59
0
  uint64_t value_64bit                    = 0;
60
0
  int number_of_characters                = 0;
61
0
  int number_of_tabs                      = 0;
62
63
0
  if( utf8_string == NULL )
64
0
  {
65
0
    libcerror_error_set(
66
0
     error,
67
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
68
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
69
0
     "%s: invalid UTF-8 string.",
70
0
     function );
71
72
0
    return( -1 );
73
0
  }
74
0
  if( *utf8_string != NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
79
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
80
0
     "%s: UTF-8 string already set.",
81
0
     function );
82
83
0
    return( -1 );
84
0
  }
85
0
  if( utf8_string_size == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
90
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
91
0
     "%s: invalid UTF-8 string size.",
92
0
     function );
93
94
0
    return( -1 );
95
0
  }
96
0
  if( media_values == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
101
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
102
0
     "%s: invalid media values.",
103
0
     function );
104
105
0
    return( -1 );
106
0
  }
107
0
  if( libewf_value_table_get_value_utf8_string_length(
108
0
       header_values,
109
0
       (uint8_t *) "model",
110
0
       6,
111
0
       &model_string_length,
112
0
       error ) == -1 )
113
0
  {
114
0
    libcerror_error_set(
115
0
     error,
116
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
117
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
118
0
     "%s: unable to retrieve header value: model length.",
119
0
     function );
120
121
0
    goto on_error;
122
0
  }
123
0
  if( libewf_value_table_get_value_utf8_string_length(
124
0
       header_values,
125
0
       (uint8_t *) "serial_number",
126
0
       14,
127
0
       &serial_number_string_length,
128
0
       error ) == -1 )
129
0
  {
130
0
    libcerror_error_set(
131
0
     error,
132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
133
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
134
0
     "%s: unable to retrieve header value: serial_number length.",
135
0
     function );
136
137
0
    goto on_error;
138
0
  }
139
0
  if( libewf_value_table_get_value_utf8_string_length(
140
0
       header_values,
141
0
       (uint8_t *) "device_label",
142
0
       13,
143
0
       &device_label_string_length,
144
0
       error ) == -1 )
145
0
  {
146
0
    libcerror_error_set(
147
0
     error,
148
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
149
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
150
0
     "%s: unable to retrieve header value: device_label length.",
151
0
     function );
152
153
0
    goto on_error;
154
0
  }
155
0
  if( libewf_value_table_get_value_utf8_string_length(
156
0
       header_values,
157
0
       (uint8_t *) "process_identifier",
158
0
       19,
159
0
       &process_identifier_string_length,
160
0
       error ) == -1 )
161
0
  {
162
0
    libcerror_error_set(
163
0
     error,
164
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
165
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
166
0
     "%s: unable to retrieve header value: process_identifier length.",
167
0
     function );
168
169
0
    goto on_error;
170
0
  }
171
  /* Determine the string size
172
   * Reserve space for:
173
   * 1 <newline>
174
   * main <newline>
175
   */
176
0
  safe_utf8_string_size = 5 + ( 2 * newline_string_length );
177
178
  /* Reserve space for:
179
   * sn <tab> md <tab> lb <tab> ts <tab> hs <tab> dc <tab> dt <tab> pid <tab> rs <tab> ls <tab> bp <tab> ph <newline>
180
   */
181
0
  number_of_characters = 25;
182
0
  number_of_tabs       = 11;
183
184
0
  safe_utf8_string_size += number_of_characters + number_of_tabs + newline_string_length;
185
186
  /* Reserve space for the values
187
   */
188
0
  safe_utf8_string_size += serial_number_string_length
189
0
                         + model_string_length
190
0
                         + device_label_string_length;
191
192
  /* If we do a streamed write reserve space for the final value
193
   */
194
0
  if( media_values->media_size == 0 )
195
0
  {
196
0
    value_64bit   = 1;
197
0
    value_64bit <<= 63;
198
0
    value_64bit  -= 1;
199
0
  }
200
0
  else
201
0
  {
202
0
    value_64bit = media_values->number_of_sectors;
203
0
  }
204
0
  if( libfvalue_string_size_from_integer(
205
0
       &number_of_sectors_string_length,
206
0
       value_64bit,
207
0
       64,
208
0
       LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
209
0
       error ) != 1 )
210
0
  {
211
0
    libcerror_error_set(
212
0
     error,
213
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
214
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
215
0
     "%s: unable to retrieve string size of number of sectors.",
216
0
     function );
217
218
0
    goto on_error;
219
0
  }
220
0
  if( number_of_sectors_string_length > 0 )
221
0
  {
222
0
    number_of_sectors_string_length -= 1;
223
224
0
    safe_utf8_string_size += number_of_sectors_string_length;
225
0
  }
226
/* TODO: hs, dc */
227
228
  /* Reserve space for the media (or drive) type */
229
0
  safe_utf8_string_size += 1;
230
231
0
  safe_utf8_string_size += process_identifier_string_length;
232
233
/* TODO: rs, ls */
234
235
0
  if( libfvalue_string_size_from_integer(
236
0
       &bytes_per_sector_string_length,
237
0
       media_values->bytes_per_sector,
238
0
       32,
239
0
       LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
240
0
       error ) != 1 )
241
0
  {
242
0
    libcerror_error_set(
243
0
     error,
244
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
245
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
246
0
     "%s: unable to retrieve string size of bytes per sector.",
247
0
     function );
248
249
0
    goto on_error;
250
0
  }
251
0
  if( bytes_per_sector_string_length > 0 )
252
0
  {
253
0
    bytes_per_sector_string_length -= 1;
254
255
0
    safe_utf8_string_size += bytes_per_sector_string_length;
256
0
  }
257
0
  if( ( media_values->media_flags & LIBEWF_MEDIA_FLAG_PHYSICAL ) != 0 )
258
0
  {
259
0
    safe_utf8_string_size += 1;
260
0
  }
261
  /* Reserve space for the tabs and 2 newlines
262
   */
263
0
  safe_utf8_string_size += number_of_tabs + ( 2 * newline_string_length );
264
265
  /* Reserve space for the end-of-string character
266
   */
267
0
  safe_utf8_string_size += 1;
268
269
0
  if( safe_utf8_string_size > MEMORY_MAXIMUM_ALLOCATION_SIZE )
270
0
  {
271
0
    libcerror_error_set(
272
0
     error,
273
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
275
0
     "%s: invalid UTF-8 string size value out of bounds.",
276
0
     function );
277
278
0
    goto on_error;
279
0
  }
280
  /* Determine the string
281
   */
282
0
  safe_utf8_string = (uint8_t *) memory_allocate(
283
0
                                  sizeof( uint8_t ) * safe_utf8_string_size );
284
285
0
  if( safe_utf8_string == NULL )
286
0
  {
287
0
    libcerror_error_set(
288
0
     error,
289
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
290
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
291
0
     "%s: unable to create UTF-8 string.",
292
0
     function );
293
294
0
    goto on_error;
295
0
  }
296
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '1';
297
298
0
  safe_utf8_string[ utf8_string_index++ ] = newline_string[ 0 ];
299
300
0
  if( newline_string_length == 2 )
301
0
  {
302
0
    safe_utf8_string[ utf8_string_index++ ] = newline_string[ 1 ];
303
0
  }
304
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'm';
305
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'a';
306
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'i';
307
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'n';
308
309
0
  safe_utf8_string[ utf8_string_index++ ] = newline_string[ 0 ];
310
311
0
  if( newline_string_length == 2 )
312
0
  {
313
0
    safe_utf8_string[ utf8_string_index++ ] = newline_string[ 1 ];
314
0
  }
315
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 's';
316
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'n';
317
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
318
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'm';
319
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'd';
320
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
321
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'l';
322
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'b';
323
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
324
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 't';
325
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 's';
326
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
327
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'h';
328
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 's';
329
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
330
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'd';
331
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'c';
332
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
333
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'd';
334
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 't';
335
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
336
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'p';
337
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'i';
338
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'd';
339
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
340
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'r';
341
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 's';
342
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
343
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'l';
344
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 's';
345
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
346
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'b';
347
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'p';
348
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
349
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'p';
350
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'h';
351
352
0
  safe_utf8_string[ utf8_string_index++ ] = newline_string[ 0 ];
353
354
0
  if( newline_string_length == 2 )
355
0
  {
356
0
    safe_utf8_string[ utf8_string_index++ ] = newline_string[ 1 ];
357
0
  }
358
0
  if( serial_number_string_length > 0 )
359
0
  {
360
0
    if( libewf_value_table_get_value_copy_to_utf8_string_with_index(
361
0
         header_values,
362
0
         (uint8_t *) "serial_number",
363
0
         14,
364
0
         safe_utf8_string,
365
0
         safe_utf8_string_size,
366
0
         &utf8_string_index,
367
0
         error ) != 1 )
368
0
    {
369
0
      libcerror_error_set(
370
0
       error,
371
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
373
0
       "%s: unable to copy header value: serial_number to string.",
374
0
       function );
375
376
0
      goto on_error;
377
0
    }
378
0
  }
379
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
380
381
0
  if( model_string_length > 0 )
382
0
  {
383
0
    if( libewf_value_table_get_value_copy_to_utf8_string_with_index(
384
0
         header_values,
385
0
         (uint8_t *) "model",
386
0
         6,
387
0
         safe_utf8_string,
388
0
         safe_utf8_string_size,
389
0
         &utf8_string_index,
390
0
         error ) != 1 )
391
0
    {
392
0
      libcerror_error_set(
393
0
       error,
394
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
395
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
396
0
       "%s: unable to copy header value: model to string.",
397
0
       function );
398
399
0
      goto on_error;
400
0
    }
401
0
  }
402
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
403
404
0
  if( device_label_string_length > 0 )
405
0
  {
406
0
    if( libewf_value_table_get_value_copy_to_utf8_string_with_index(
407
0
         header_values,
408
0
         (uint8_t *) "device_label",
409
0
         13,
410
0
         safe_utf8_string,
411
0
         safe_utf8_string_size,
412
0
         &utf8_string_index,
413
0
         error ) != 1 )
414
0
    {
415
0
      libcerror_error_set(
416
0
       error,
417
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
419
0
       "%s: unable to copy header value: device_label to string.",
420
0
       function );
421
422
0
      goto on_error;
423
0
    }
424
0
  }
425
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
426
427
0
  if( number_of_sectors_string_length > 0 )
428
0
  {
429
    /* If we do a streamed write reserve space for the final value
430
     */
431
0
    if( media_values->media_size == 0 )
432
0
    {
433
0
      value_64bit   = 1;
434
0
      value_64bit <<= 63;
435
0
      value_64bit  -= 1;
436
0
    }
437
0
    else
438
0
    {
439
0
      value_64bit = media_values->number_of_sectors;
440
0
    }
441
0
    if( libfvalue_utf8_string_with_index_copy_from_integer(
442
0
         safe_utf8_string,
443
0
         safe_utf8_string_size,
444
0
         &utf8_string_index,
445
0
         value_64bit,
446
0
         64,
447
0
         LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
448
0
         error ) != 1 )
449
0
    {
450
0
      libcerror_error_set(
451
0
       error,
452
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
453
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
454
0
       "%s: unable to copy number of sectors to string.",
455
0
       function );
456
457
0
      goto on_error;
458
0
    }
459
0
    utf8_string_index--;
460
0
  }
461
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
462
463
/* TODO: set hs */
464
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
465
466
/* TODO: set dc */
467
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
468
469
/* TODO add support for media types: RAM disk, PALM */
470
0
  switch( media_values->media_type )
471
0
  {
472
0
    case LIBEWF_MEDIA_TYPE_REMOVABLE:
473
0
      safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'r';
474
0
      break;
475
476
0
    case LIBEWF_MEDIA_TYPE_FIXED:
477
0
      safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'f';
478
0
      break;
479
480
0
    case LIBEWF_MEDIA_TYPE_OPTICAL:
481
0
      safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'c';
482
0
      break;
483
484
0
    case LIBEWF_MEDIA_TYPE_SINGLE_FILES:
485
0
      safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'l';
486
0
      break;
487
488
0
    case LIBEWF_MEDIA_TYPE_MEMORY:
489
0
      safe_utf8_string[ utf8_string_index++ ] = (uint8_t) 'm';
490
0
      break;
491
492
0
    default:
493
0
      libcerror_error_set(
494
0
       error,
495
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
496
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
497
0
       "%s: unsupported media type.",
498
0
       function );
499
500
0
      goto on_error;
501
0
  }
502
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
503
504
0
  if( process_identifier_string_length > 0 )
505
0
  {
506
0
    if( libewf_value_table_get_value_copy_to_utf8_string_with_index(
507
0
         header_values,
508
0
         (uint8_t *) "process_identifier",
509
0
         19,
510
0
         safe_utf8_string,
511
0
         safe_utf8_string_size,
512
0
         &utf8_string_index,
513
0
         error ) != 1 )
514
0
    {
515
0
      libcerror_error_set(
516
0
       error,
517
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
518
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
519
0
       "%s: unable to copy header value: process_identifier to string.",
520
0
       function );
521
522
0
      goto on_error;
523
0
    }
524
0
  }
525
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
526
527
/* TODO: rs */
528
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
529
530
/* TODO: ls */
531
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
532
533
0
  if( bytes_per_sector_string_length > 0 )
534
0
  {
535
0
    if( libfvalue_utf8_string_with_index_copy_from_integer(
536
0
         safe_utf8_string,
537
0
         safe_utf8_string_size,
538
0
         &utf8_string_index,
539
0
         media_values->bytes_per_sector,
540
0
         32,
541
0
         LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
542
0
         error ) != 1 )
543
0
    {
544
0
      libcerror_error_set(
545
0
       error,
546
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
547
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
548
0
       "%s: unable to copy bytes per sector to string.",
549
0
       function );
550
551
0
      goto on_error;
552
0
    }
553
0
    utf8_string_index--;
554
0
  }
555
0
  safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '\t';
556
557
0
  if( ( media_values->media_flags & LIBEWF_MEDIA_FLAG_PHYSICAL ) != 0 )
558
0
  {
559
0
    safe_utf8_string[ utf8_string_index++ ] = (uint8_t) '1';
560
0
  }
561
0
  safe_utf8_string[ utf8_string_index++ ] = newline_string[ 0 ];
562
563
0
  if( newline_string_length == 2 )
564
0
  {
565
0
    safe_utf8_string[ utf8_string_index++ ] = newline_string[ 1 ];
566
0
  }
567
0
  safe_utf8_string[ utf8_string_index++ ] = newline_string[ 0 ];
568
569
0
  if( newline_string_length == 2 )
570
0
  {
571
0
    safe_utf8_string[ utf8_string_index++ ] = newline_string[ 1 ];
572
0
  }
573
0
  safe_utf8_string[ utf8_string_index++ ] = 0;
574
575
0
  *utf8_string      = safe_utf8_string;
576
0
  *utf8_string_size = safe_utf8_string_size;
577
578
0
  return( 1 );
579
580
0
on_error:
581
0
  if( safe_utf8_string != NULL )
582
0
  {
583
0
    memory_free(
584
0
     safe_utf8_string );
585
0
  }
586
0
  return( -1 );
587
0
}
588
589
/* Generate device information
590
 * Sets device_information and device_information_size
591
 * Returns 1 if successful or -1 on error
592
 */
593
int libewf_device_information_generate(
594
     uint8_t **device_information,
595
     size_t *device_information_size,
596
     libewf_media_values_t *media_values,
597
     libfvalue_table_t *header_values,
598
     libcerror_error_t **error )
599
0
{
600
0
  uint8_t *safe_device_information    = NULL;
601
0
  uint8_t *utf8_string                = NULL;
602
0
  static char *function               = "libewf_device_information_generate";
603
0
  size_t safe_device_information_size = 0;
604
0
  size_t utf8_string_size             = 0;
605
606
0
  if( device_information == NULL )
607
0
  {
608
0
    libcerror_error_set(
609
0
     error,
610
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
611
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
612
0
     "%s: invalid device information.",
613
0
     function );
614
615
0
    return( -1 );
616
0
  }
617
0
  if( *device_information != NULL )
618
0
  {
619
0
    libcerror_error_set(
620
0
     error,
621
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
622
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
623
0
     "%s: device information already created.",
624
0
     function );
625
626
0
    return( -1 );
627
0
  }
628
0
  if( device_information_size == NULL )
629
0
  {
630
0
    libcerror_error_set(
631
0
     error,
632
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
633
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
634
0
     "%s: invalid device information size.",
635
0
     function );
636
637
0
    return( -1 );
638
0
  }
639
0
  if( libewf_device_information_generate_utf8_string(
640
0
       &utf8_string,
641
0
       &utf8_string_size,
642
0
       media_values,
643
0
       header_values,
644
0
       error ) != 1 )
645
0
  {
646
0
    libcerror_error_set(
647
0
     error,
648
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
649
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
650
0
     "%s: unable to create UTF-8 device information string.",
651
0
     function );
652
653
0
    goto on_error;
654
0
  }
655
#if defined( HAVE_DEBUG_OUTPUT )
656
  if( libcnotify_verbose != 0 )
657
  {
658
    libcnotify_printf(
659
    "%s: device information string:\n%s",
660
     function,
661
     utf8_string );
662
  }
663
#endif
664
0
  if( libuna_utf16_stream_size_from_utf8(
665
0
       utf8_string,
666
0
       utf8_string_size,
667
0
       &safe_device_information_size,
668
0
       error ) != 1 )
669
0
  {
670
0
    libcerror_error_set(
671
0
     error,
672
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
673
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
674
0
     "%s: unable to determine device information size.",
675
0
     function );
676
677
0
    goto on_error;
678
0
  }
679
0
  if( ( safe_device_information_size == 0 )
680
0
   || ( safe_device_information_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
681
0
  {
682
0
    libcerror_error_set(
683
0
     error,
684
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
685
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
686
0
     "%s: invalid device information size value out of bounds.",
687
0
     function );
688
689
0
    goto on_error;
690
0
  }
691
0
  safe_device_information = (uint8_t *) memory_allocate(
692
0
                                         sizeof( uint8_t ) * safe_device_information_size );
693
694
0
  if( safe_device_information == NULL )
695
0
  {
696
0
    libcerror_error_set(
697
0
     error,
698
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
699
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
700
0
     "%s: unable to create device information.",
701
0
     function );
702
703
0
    goto on_error;
704
0
  }
705
0
  if( libuna_utf16_stream_copy_from_utf8(
706
0
       safe_device_information,
707
0
       safe_device_information_size,
708
0
       LIBUNA_ENDIAN_LITTLE,
709
0
       utf8_string,
710
0
       utf8_string_size,
711
0
       error ) != 1 )
712
0
  {
713
0
    libcerror_error_set(
714
0
     error,
715
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
716
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
717
0
     "%s: unable to set device information.",
718
0
     function );
719
720
0
    goto on_error;
721
0
  }
722
0
  memory_free(
723
0
   utf8_string );
724
725
0
  *device_information      = safe_device_information;
726
0
  *device_information_size = safe_device_information_size;
727
728
0
  return( 1 );
729
730
0
on_error:
731
0
  if( utf8_string != NULL )
732
0
  {
733
0
    memory_free(
734
0
     utf8_string );
735
0
  }
736
0
  if( safe_device_information != NULL )
737
0
  {
738
0
    memory_free(
739
0
     safe_device_information );
740
0
  }
741
0
  return( -1 );
742
0
}
743
744
/* Parses an UTF-8 encoded device information string
745
 * Returns 1 if successful or -1 on error
746
 */
747
int libewf_device_information_parse_utf8_string(
748
     const uint8_t *utf8_string,
749
     size_t utf8_string_size,
750
     libewf_media_values_t *media_values,
751
     libfvalue_table_t *header_values,
752
     libcerror_error_t **error )
753
0
{
754
0
  libfvalue_split_utf8_string_t *lines  = NULL;
755
0
  libfvalue_split_utf8_string_t *types  = NULL;
756
0
  libfvalue_split_utf8_string_t *values = NULL;
757
0
  uint8_t *line_string                  = NULL;
758
0
  uint8_t *type_string                  = NULL;
759
0
  uint8_t *value_string                 = NULL;
760
0
  static char *function                 = "libewf_device_information_parse_utf8_string";
761
0
  size_t line_string_size               = 0;
762
0
  size_t type_string_size               = 0;
763
0
  size_t value_string_size              = 0;
764
0
  int number_of_lines                   = 0;
765
0
  int number_of_types                   = 0;
766
0
  int number_of_values                  = 0;
767
0
  int value_index                       = 0;
768
769
0
  if( utf8_string == NULL )
770
0
  {
771
0
    libcerror_error_set(
772
0
     error,
773
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
774
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
775
0
     "%s: invalid UTF-8 string.",
776
0
     function );
777
778
0
    return( -1 );
779
0
  }
780
0
  if( libfvalue_utf8_string_split(
781
0
       utf8_string,
782
0
       utf8_string_size,
783
0
       (uint8_t) '\n',
784
0
       &lines,
785
0
       error ) != 1 )
786
0
  {
787
0
    libcerror_error_set(
788
0
     error,
789
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
790
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
791
0
     "%s: unable to split UTF-8 string into lines.",
792
0
     function );
793
794
0
    goto on_error;
795
0
  }
796
0
  if( libfvalue_split_utf8_string_get_number_of_segments(
797
0
       lines,
798
0
       &number_of_lines,
799
0
       error ) != 1 )
800
0
  {
801
0
    libcerror_error_set(
802
0
     error,
803
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
804
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
805
0
     "%s: unable to retrieve number of lines.",
806
0
     function );
807
808
0
    goto on_error;
809
0
  }
810
0
  if( number_of_lines > 0 )
811
0
  {
812
0
    if( libfvalue_split_utf8_string_get_segment_by_index(
813
0
         lines,
814
0
         0,
815
0
         &line_string,
816
0
         &line_string_size,
817
0
         error ) != 1 )
818
0
    {
819
0
      libcerror_error_set(
820
0
       error,
821
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
822
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
823
0
       "%s: unable to retrieve line string: 0.",
824
0
       function );
825
826
0
      goto on_error;
827
0
    }
828
0
    if( line_string == NULL )
829
0
    {
830
0
      libcerror_error_set(
831
0
       error,
832
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
833
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
834
0
       "%s: missing line string: 0.",
835
0
       function );
836
837
0
      goto on_error;
838
0
    }
839
0
    if( ( line_string == NULL )
840
0
     || ( line_string_size < 2 )
841
0
     || ( line_string[ 0 ] == 0 ) )
842
0
    {
843
0
      libcerror_error_set(
844
0
       error,
845
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
846
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
847
0
       "%s: missing line string: 0.",
848
0
       function );
849
850
0
      goto on_error;
851
0
    }
852
    /* Remove trailing carriage return
853
     */
854
0
    else if( line_string[ line_string_size - 2 ] == (uint8_t) '\r' )
855
0
    {
856
0
      line_string[ line_string_size - 2 ] = 0;
857
858
0
      line_string_size -= 1;
859
0
    }
860
0
    if( line_string_size != 2 )
861
0
    {
862
0
      libcerror_error_set(
863
0
       error,
864
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
865
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
866
0
       "%s: unsupported line string: 0.",
867
0
       function );
868
869
0
      goto on_error;
870
0
    }
871
0
    if( line_string[ 0 ] < (uint8_t) '1' )
872
0
    {
873
0
      libcerror_error_set(
874
0
       error,
875
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
876
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
877
0
       "%s: unsupported line string: 0.",
878
0
       function );
879
880
0
      goto on_error;
881
0
    }
882
0
    if( libfvalue_split_utf8_string_get_segment_by_index(
883
0
         lines,
884
0
         1,
885
0
         &line_string,
886
0
         &line_string_size,
887
0
         error ) != 1 )
888
0
    {
889
0
      libcerror_error_set(
890
0
       error,
891
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
892
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
893
0
       "%s: unable to retrieve line string: 1.",
894
0
       function );
895
896
0
      goto on_error;
897
0
    }
898
0
    if( line_string == NULL )
899
0
    {
900
0
      libcerror_error_set(
901
0
       error,
902
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
903
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
904
0
       "%s: missing line string: 1.",
905
0
       function );
906
907
0
      goto on_error;
908
0
    }
909
0
    if( ( line_string == NULL )
910
0
     || ( line_string_size < 5 )
911
0
     || ( line_string[ 0 ] == 0 ) )
912
0
    {
913
0
      libcerror_error_set(
914
0
       error,
915
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
916
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
917
0
       "%s: missing line string: 1.",
918
0
       function );
919
920
0
      goto on_error;
921
0
    }
922
    /* Remove trailing carriage return
923
     */
924
0
    else if( line_string[ line_string_size - 2 ] == (uint8_t) '\r' )
925
0
    {
926
0
      line_string[ line_string_size - 2 ] = 0;
927
928
0
      line_string_size -= 1;
929
0
    }
930
0
    if( line_string_size != 5 )
931
0
    {
932
0
      libcerror_error_set(
933
0
       error,
934
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
935
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
936
0
       "%s: unsupported line string: 1.",
937
0
       function );
938
939
0
      goto on_error;
940
0
    }
941
0
    if( ( line_string[ 0 ] != (uint8_t) 'm' )
942
0
     || ( line_string[ 1 ] != (uint8_t) 'a' )
943
0
     || ( line_string[ 2 ] != (uint8_t) 'i' )
944
0
     || ( line_string[ 3 ] != (uint8_t) 'n' ) )
945
0
    {
946
0
      libcerror_error_set(
947
0
       error,
948
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
949
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
950
0
       "%s: unsupported line string: 1.",
951
0
       function );
952
953
0
      goto on_error;
954
0
    }
955
0
    if( libfvalue_split_utf8_string_get_segment_by_index(
956
0
         lines,
957
0
         2,
958
0
         &line_string,
959
0
         &line_string_size,
960
0
         error ) != 1 )
961
0
    {
962
0
      libcerror_error_set(
963
0
       error,
964
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
965
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
966
0
       "%s: unable to retrieve line string: 2.",
967
0
       function );
968
969
0
      goto on_error;
970
0
    }
971
0
    if( libfvalue_utf8_string_split(
972
0
         line_string,
973
0
         line_string_size,
974
0
         (uint8_t) '\t',
975
0
         &types,
976
0
         error ) != 1 )
977
0
    {
978
0
      libcerror_error_set(
979
0
       error,
980
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
981
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
982
0
       "%s: unable to split device information string into types.",
983
0
       function );
984
985
0
      goto on_error;
986
0
    }
987
0
    if( libfvalue_split_utf8_string_get_number_of_segments(
988
0
         types,
989
0
         &number_of_types,
990
0
         error ) != 1 )
991
0
    {
992
0
      libcerror_error_set(
993
0
       error,
994
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
995
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
996
0
       "%s: unable to retrieve number of types.",
997
0
       function );
998
999
0
      goto on_error;
1000
0
    }
1001
0
    if( libfvalue_split_utf8_string_get_segment_by_index(
1002
0
         lines,
1003
0
         3,
1004
0
         &line_string,
1005
0
         &line_string_size,
1006
0
         error ) != 1 )
1007
0
    {
1008
0
      libcerror_error_set(
1009
0
       error,
1010
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1011
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1012
0
       "%s: unable to retrieve line string: 3.",
1013
0
       function );
1014
1015
0
      goto on_error;
1016
0
    }
1017
0
    if( libfvalue_utf8_string_split(
1018
0
         line_string,
1019
0
         line_string_size,
1020
0
         (uint8_t) '\t',
1021
0
         &values,
1022
0
         error ) != 1 )
1023
0
    {
1024
0
      libcerror_error_set(
1025
0
       error,
1026
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1027
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1028
0
       "%s: unable to split device information string into values.",
1029
0
       function );
1030
1031
0
      goto on_error;
1032
0
    }
1033
0
    if( libfvalue_split_utf8_string_get_number_of_segments(
1034
0
         values,
1035
0
         &number_of_values,
1036
0
         error ) != 1 )
1037
0
    {
1038
0
      libcerror_error_set(
1039
0
       error,
1040
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1041
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1042
0
       "%s: unable to retrieve number of values.",
1043
0
       function );
1044
1045
0
      goto on_error;
1046
0
    }
1047
#if defined( HAVE_VERBOSE_OUTPUT )
1048
    if( number_of_types != number_of_values )
1049
    {
1050
      if( libcnotify_verbose != 0 )
1051
      {
1052
        libcnotify_printf(
1053
        "%s: mismatch in number of types and values.\n",
1054
         function );
1055
      }
1056
    }
1057
#endif
1058
0
    for( value_index = 0;
1059
0
         value_index < number_of_types;
1060
0
         value_index++ )
1061
0
    {
1062
0
      if( libfvalue_split_utf8_string_get_segment_by_index(
1063
0
           types,
1064
0
           value_index,
1065
0
           &type_string,
1066
0
           &type_string_size,
1067
0
           error ) != 1 )
1068
0
      {
1069
0
        libcerror_error_set(
1070
0
         error,
1071
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1072
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1073
0
         "%s: unable to retrieve type string: %d.",
1074
0
         function,
1075
0
         value_index );
1076
1077
0
        goto on_error;
1078
0
      }
1079
0
      if( value_index >= number_of_values )
1080
0
      {
1081
0
        value_string      = NULL;
1082
0
        value_string_size = 0;
1083
0
      }
1084
0
      else if( libfvalue_split_utf8_string_get_segment_by_index(
1085
0
                values,
1086
0
                value_index,
1087
0
                &value_string,
1088
0
                &value_string_size,
1089
0
                error ) != 1 )
1090
0
      {
1091
0
        libcerror_error_set(
1092
0
         error,
1093
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1095
0
         "%s: unable to retrieve value string: %d.",
1096
0
         function,
1097
0
         value_index );
1098
1099
0
        goto on_error;
1100
0
      }
1101
0
      if( libewf_device_information_parse_utf8_string_value(
1102
0
           type_string,
1103
0
           type_string_size,
1104
0
           value_string,
1105
0
           value_string_size,
1106
0
           value_index,
1107
0
           media_values,
1108
0
           header_values,
1109
0
           error ) != 1 )
1110
0
      {
1111
0
        libcerror_error_set(
1112
0
         error,
1113
0
         LIBCERROR_ERROR_DOMAIN_CONVERSION,
1114
0
         LIBCERROR_CONVERSION_ERROR_GENERIC,
1115
0
         "%s: unable to parse UTF-8 string value: %d.",
1116
0
         function,
1117
0
         value_index );
1118
1119
0
        goto on_error;
1120
0
      }
1121
0
    }
1122
0
    if( libfvalue_split_utf8_string_free(
1123
0
         &values,
1124
0
         error ) != 1 )
1125
0
    {
1126
0
      libcerror_error_set(
1127
0
       error,
1128
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1129
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1130
0
       "%s: unable to free split values.",
1131
0
       function );
1132
1133
0
      goto on_error;
1134
0
    }
1135
0
    if( libfvalue_split_utf8_string_free(
1136
0
         &types,
1137
0
         error ) != 1 )
1138
0
    {
1139
0
      libcerror_error_set(
1140
0
       error,
1141
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1142
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1143
0
       "%s: unable to free split types.",
1144
0
       function );
1145
1146
0
      goto on_error;
1147
0
    }
1148
0
  }
1149
0
  if( libfvalue_split_utf8_string_free(
1150
0
       &lines,
1151
0
       error ) != 1 )
1152
0
  {
1153
0
    libcerror_error_set(
1154
0
     error,
1155
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1156
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1157
0
     "%s: unable to free split lines.",
1158
0
     function );
1159
1160
0
    goto on_error;
1161
0
  }
1162
#if defined( HAVE_DEBUG_OUTPUT )
1163
  if( libcnotify_verbose != 0 )
1164
  {
1165
    libcnotify_printf(
1166
    "\n" );
1167
  }
1168
#endif
1169
0
  return( 1 );
1170
1171
0
on_error:
1172
0
  if( values != NULL )
1173
0
  {
1174
0
    libfvalue_split_utf8_string_free(
1175
0
     &values,
1176
0
     NULL );
1177
0
  }
1178
0
  if( types != NULL )
1179
0
  {
1180
0
    libfvalue_split_utf8_string_free(
1181
0
     &types,
1182
0
     NULL );
1183
0
  }
1184
0
  if( lines != NULL )
1185
0
  {
1186
0
    libfvalue_split_utf8_string_free(
1187
0
     &lines,
1188
0
     NULL );
1189
0
  }
1190
0
  return( -1 );
1191
0
}
1192
1193
/* Parses an UTF-8 encoded device information string value
1194
 * Returns 1 if successful or -1 on error
1195
 */
1196
int libewf_device_information_parse_utf8_string_value(
1197
     uint8_t *type_string,
1198
     size_t type_string_size,
1199
     uint8_t *value_string,
1200
     size_t value_string_size,
1201
     int value_index,
1202
     libewf_media_values_t *media_values,
1203
     libfvalue_table_t *header_values,
1204
     libcerror_error_t **error )
1205
0
{
1206
0
  uint8_t *identifier    = NULL;
1207
0
  static char *function  = "libewf_device_information_parse_utf8_string_value";
1208
0
  size_t identifier_size = 0;
1209
0
  uint64_t value_64bit   = 0;
1210
1211
0
  if( ( type_string == NULL )
1212
0
   || ( type_string_size < 2 )
1213
0
   || ( type_string[ 0 ] == 0 ) )
1214
0
  {
1215
0
    libcerror_error_set(
1216
0
     error,
1217
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1218
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1219
0
     "%s: missing type string: %d.",
1220
0
     function,
1221
0
     value_index );
1222
1223
0
    return( -1 );
1224
0
  }
1225
0
  if( media_values == NULL )
1226
0
  {
1227
0
    libcerror_error_set(
1228
0
     error,
1229
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1230
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1231
0
     "%s: invalid media values.",
1232
0
     function );
1233
1234
0
    return( -1 );
1235
0
  }
1236
0
  if( header_values == NULL )
1237
0
  {
1238
0
    libcerror_error_set(
1239
0
     error,
1240
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1241
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1242
0
     "%s: invalid header values.",
1243
0
     function );
1244
1245
0
    return( -1 );
1246
0
  }
1247
  /* Remove trailing carriage return
1248
   */
1249
0
  if( type_string[ type_string_size - 2 ] == (uint8_t) '\r' )
1250
0
  {
1251
0
    type_string[ type_string_size - 2 ] = 0;
1252
1253
0
    type_string_size -= 1;
1254
0
  }
1255
0
  if( ( value_string == NULL )
1256
0
   || ( value_string_size < 2 )
1257
0
   || ( value_string[ 0 ] == 0 ) )
1258
0
  {
1259
0
    value_string      = NULL;
1260
0
    value_string_size = 0;
1261
0
  }
1262
  /* Remove trailing carriage return
1263
   */
1264
0
  else if( value_string[ value_string_size - 2 ] == (uint8_t) '\r' )
1265
0
  {
1266
0
    value_string[ value_string_size - 2 ] = 0;
1267
1268
0
    value_string_size -= 1;
1269
0
  }
1270
#if defined( HAVE_VERBOSE_OUTPUT )
1271
  if( libcnotify_verbose != 0 )
1272
  {
1273
    libcnotify_printf(
1274
     "%s: type: %s with value: %s.\n",
1275
     function,
1276
     (char *) type_string,
1277
     (char *) value_string );
1278
  }
1279
#endif
1280
  /* Ignore empty values
1281
   */
1282
0
  if( value_string == NULL )
1283
0
  {
1284
0
    return( 1 );
1285
0
  }
1286
0
  identifier      = NULL;
1287
0
  identifier_size = 0;
1288
1289
0
  if( type_string_size == 4 )
1290
0
  {
1291
0
    if( ( type_string[ 0 ] == (uint8_t) 'p' )
1292
0
     && ( type_string[ 1 ] == (uint8_t) 'i' )
1293
0
     && ( type_string[ 2 ] == (uint8_t) 'd' ) )
1294
0
    {
1295
0
      identifier      = (uint8_t *) "process_identifier";
1296
0
      identifier_size = 19;
1297
0
    }
1298
0
  }
1299
0
  else if( type_string_size == 3 )
1300
0
  {
1301
0
    if( ( type_string[ 0 ] == (uint8_t) 'b' )
1302
0
     && ( type_string[ 1 ] == (uint8_t) 'p' ) )
1303
0
    {
1304
0
      if( libfvalue_utf8_string_copy_to_integer(
1305
0
           value_string,
1306
0
           value_string_size,
1307
0
           &value_64bit,
1308
0
           32,
1309
0
           LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
1310
0
           error ) != 1 )
1311
0
      {
1312
0
        libcerror_error_set(
1313
0
         error,
1314
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1315
0
         LIBCERROR_MEMORY_ERROR_SET_FAILED,
1316
0
         "%s: unable to set bytes per sector.",
1317
0
         function );
1318
1319
0
        return( -1 );
1320
0
      }
1321
0
      media_values->bytes_per_sector = (uint32_t) value_64bit;
1322
0
    }
1323
0
    else if( ( type_string[ 0 ] == (uint8_t) 'd' )
1324
0
          && ( type_string[ 1 ] == (uint8_t) 'c' ) )
1325
0
    {
1326
0
      if( libfvalue_utf8_string_copy_to_integer(
1327
0
           value_string,
1328
0
           value_string_size,
1329
0
           &value_64bit,
1330
0
           64,
1331
0
           LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
1332
0
           error ) != 1 )
1333
0
      {
1334
0
        libcerror_error_set(
1335
0
         error,
1336
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1337
0
         LIBCERROR_MEMORY_ERROR_SET_FAILED,
1338
0
         "%s: unable to set number of DCO protected sectors.",
1339
0
         function );
1340
1341
0
        return( -1 );
1342
0
      }
1343
/* TODO number of DCO protected sectors */
1344
0
    }
1345
0
    else if( ( type_string[ 0 ] == (uint8_t) 'd' )
1346
0
          && ( type_string[ 1 ] == (uint8_t) 't' ) )
1347
0
    {
1348
0
      if( value_string_size == 2 )
1349
0
      {
1350
0
        switch( value_string[ 0 ] )
1351
0
        {
1352
/* TODO need the EWF1 equivalent value
1353
          case (uint8_t) 'a':
1354
            media_values->media_type = LIBEWF_MEDIA_TYPE_RAM_DISK;
1355
            break;
1356
*/
1357
1358
0
          case (uint8_t) 'c':
1359
0
            media_values->media_type = LIBEWF_MEDIA_TYPE_OPTICAL;
1360
0
            break;
1361
1362
0
          case (uint8_t) 'f':
1363
0
            media_values->media_type = LIBEWF_MEDIA_TYPE_FIXED;
1364
0
            break;
1365
1366
0
          case (uint8_t) 'l':
1367
0
            media_values->media_type = LIBEWF_MEDIA_TYPE_SINGLE_FILES;
1368
0
            break;
1369
1370
0
          case (uint8_t) 'm':
1371
0
            media_values->media_type = LIBEWF_MEDIA_TYPE_MEMORY;
1372
0
            break;
1373
1374
/* TODO need the EWF1 equivalent value
1375
          case (uint8_t) 'p':
1376
            media_values->media_type = LIBEWF_MEDIA_TYPE_PALM;
1377
            break;
1378
*/
1379
1380
0
          case (uint8_t) 'r':
1381
0
            media_values->media_type = LIBEWF_MEDIA_TYPE_REMOVABLE;
1382
0
            break;
1383
1384
#if defined( HAVE_DEBUG_OUTPUT )
1385
          default:
1386
            if( libcnotify_verbose != 0 )
1387
            {
1388
              libcnotify_printf(
1389
              "%s: unsupported drive type.\n",
1390
               function );
1391
            }
1392
            break;
1393
#endif
1394
0
        }
1395
0
      }
1396
#if defined( HAVE_DEBUG_OUTPUT )
1397
      else if( libcnotify_verbose != 0 )
1398
      {
1399
        libcnotify_printf(
1400
        "%s: unsupported drive type.\n",
1401
         function );
1402
      }
1403
#endif
1404
0
    }
1405
0
    else if( ( type_string[ 0 ] == (uint8_t) 'h' )
1406
0
          && ( type_string[ 1 ] == (uint8_t) 's' ) )
1407
0
    {
1408
0
      if( libfvalue_utf8_string_copy_to_integer(
1409
0
           value_string,
1410
0
           value_string_size,
1411
0
           &value_64bit,
1412
0
           64,
1413
0
           LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
1414
0
           error ) != 1 )
1415
0
      {
1416
0
        libcerror_error_set(
1417
0
         error,
1418
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1419
0
         LIBCERROR_MEMORY_ERROR_SET_FAILED,
1420
0
         "%s: unable to set number of HPA protected sectors.",
1421
0
         function );
1422
1423
0
        return( -1 );
1424
0
      }
1425
/* TODO number of HPA protected sectors */
1426
0
    }
1427
0
    else if( ( type_string[ 0 ] == (uint8_t) 'l' )
1428
0
          && ( type_string[ 1 ] == (uint8_t) 'b' ) )
1429
0
    {
1430
0
      identifier      = (uint8_t *) "device_label";
1431
0
      identifier_size = 13;
1432
0
    }
1433
0
    else if( ( type_string[ 0 ] == (uint8_t) 'l' )
1434
0
          && ( type_string[ 1 ] == (uint8_t) 's' ) )
1435
0
    {
1436
/* TODO number of sectors of SMART logs */
1437
0
    }
1438
0
    else if( ( type_string[ 0 ] == (uint8_t) 'm' )
1439
0
          && ( type_string[ 1 ] == (uint8_t) 'd' ) )
1440
0
    {
1441
0
      identifier      = (uint8_t *) "model";
1442
0
      identifier_size = 6;
1443
0
    }
1444
0
    else if( ( type_string[ 0 ] == (uint8_t) 'p' )
1445
0
          && ( type_string[ 1 ] == (uint8_t) 'h' ) )
1446
0
    {
1447
0
      if( ( value_string_size == 2 )
1448
0
       && ( value_string[ 0 ] == (uint8_t) '1' ) )
1449
0
      {
1450
0
        media_values->media_flags |= LIBEWF_MEDIA_FLAG_PHYSICAL;
1451
0
      }
1452
#if defined( HAVE_DEBUG_OUTPUT )
1453
      else if( libcnotify_verbose != 0 )
1454
      {
1455
        libcnotify_printf(
1456
        "%s: unsupported is physical.\n",
1457
         function );
1458
      }
1459
#endif
1460
0
    }
1461
0
    else if( ( type_string[ 0 ] == (uint8_t) 'r' )
1462
0
          && ( type_string[ 1 ] == (uint8_t) 's' ) )
1463
0
    {
1464
/* TODO number of sectors of PALM RAM device */
1465
0
    }
1466
0
    else if( ( type_string[ 0 ] == (uint8_t) 's' )
1467
0
          && ( type_string[ 1 ] == (uint8_t) 'n' ) )
1468
0
    {
1469
0
      identifier      = (uint8_t *) "serial_number";
1470
0
      identifier_size = 14;
1471
0
    }
1472
0
    else if( ( type_string[ 0 ] == (uint8_t) 't' )
1473
0
          && ( type_string[ 1 ] == (uint8_t) 's' ) )
1474
0
    {
1475
0
      if( libfvalue_utf8_string_copy_to_integer(
1476
0
           value_string,
1477
0
           value_string_size,
1478
0
           &value_64bit,
1479
0
           64,
1480
0
           LIBFVALUE_INTEGER_FORMAT_TYPE_DECIMAL_UNSIGNED,
1481
0
           error ) != 1 )
1482
0
      {
1483
0
        libcerror_error_set(
1484
0
         error,
1485
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1486
0
         LIBCERROR_MEMORY_ERROR_SET_FAILED,
1487
0
         "%s: unable to set number of sectors.",
1488
0
         function );
1489
1490
0
        return( -1 );
1491
0
      }
1492
0
      media_values->number_of_sectors = value_64bit;
1493
0
    }
1494
0
  }
1495
0
  if( identifier != NULL )
1496
0
  {
1497
0
    if( libewf_value_table_set_value_by_identifier(
1498
0
         header_values,
1499
0
         identifier,
1500
0
         identifier_size,
1501
0
         value_string,
1502
0
         value_string_size,
1503
0
         error ) != 1 )
1504
0
    {
1505
0
      libcerror_error_set(
1506
0
       error,
1507
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1508
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1509
0
       "%s: unable to set header value: %s.",
1510
0
       function,
1511
0
       (char *) identifier );
1512
1513
0
      return( -1 );
1514
0
    }
1515
0
  }
1516
0
  return( 1 );
1517
0
}
1518
1519
/* Parses EWF version 2 device information
1520
 * Returns 1 if successful or -1 on error
1521
 */
1522
int libewf_device_information_parse(
1523
     const uint8_t *device_information,
1524
     size_t device_information_size,
1525
     libewf_media_values_t *media_values,
1526
     libfvalue_table_t *header_values,
1527
     libcerror_error_t **error )
1528
0
{
1529
0
  uint8_t *utf8_string    = NULL;
1530
0
  static char *function   = "libewf_device_information_parse";
1531
0
  size_t utf8_string_size = 0;
1532
1533
0
  if( device_information == NULL )
1534
0
  {
1535
0
    libcerror_error_set(
1536
0
     error,
1537
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1538
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1539
0
     "%s: invalid device information.",
1540
0
     function );
1541
1542
0
    return( -1 );
1543
0
  }
1544
0
  if( libuna_utf8_string_size_from_utf16_stream(
1545
0
       device_information,
1546
0
       device_information_size,
1547
0
       0,
1548
0
       &utf8_string_size,
1549
0
       error ) != 1 )
1550
0
  {
1551
0
    libcerror_error_set(
1552
0
     error,
1553
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
1554
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
1555
0
     "%s: unable to determine UTF-8 string size.",
1556
0
     function );
1557
1558
0
    goto on_error;
1559
0
  }
1560
0
  if( ( utf8_string_size == 0 )
1561
0
   || ( utf8_string_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
1562
0
  {
1563
0
    libcerror_error_set(
1564
0
     error,
1565
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1566
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1567
0
     "%s: invalid UTF-8 string size value out of bounds.",
1568
0
     function );
1569
1570
0
    goto on_error;
1571
0
  }
1572
0
  utf8_string = (uint8_t *) memory_allocate(
1573
0
                             sizeof( uint8_t ) * utf8_string_size );
1574
1575
0
  if( utf8_string == NULL )
1576
0
  {
1577
0
    libcerror_error_set(
1578
0
     error,
1579
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1580
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1581
0
     "%s: unable to create UTF-8 string.",
1582
0
     function );
1583
1584
0
    goto on_error;
1585
0
  }
1586
0
  if( libuna_utf8_string_copy_from_utf16_stream(
1587
0
       utf8_string,
1588
0
       utf8_string_size,
1589
0
       device_information,
1590
0
       device_information_size,
1591
0
       0,
1592
0
       error ) != 1 )
1593
0
  {
1594
0
    libcerror_error_set(
1595
0
     error,
1596
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1597
0
     LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1598
0
     "%s: unable to copy device information to UTF-8 string.",
1599
0
     function );
1600
1601
0
    goto on_error;
1602
0
  }
1603
#if defined( HAVE_DEBUG_OUTPUT )
1604
  if( libcnotify_verbose != 0 )
1605
  {
1606
    libcnotify_printf(
1607
    "%s: device information string:\n%s",
1608
     function,
1609
     utf8_string );
1610
  }
1611
#endif
1612
0
  if( libewf_device_information_parse_utf8_string(
1613
0
       utf8_string,
1614
0
       utf8_string_size,
1615
0
       media_values,
1616
0
       header_values,
1617
0
       error ) != 1 )
1618
0
  {
1619
0
    libcerror_error_set(
1620
0
     error,
1621
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
1622
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
1623
0
     "%s: unable to parse UTF-8 string.",
1624
0
     function );
1625
1626
0
    goto on_error;
1627
0
  }
1628
0
  memory_free(
1629
0
   utf8_string );
1630
1631
0
  return( 1 );
1632
1633
0
on_error:
1634
0
  if( utf8_string != NULL )
1635
0
  {
1636
0
    memory_free(
1637
0
     utf8_string );
1638
0
  }
1639
0
  return( -1 );
1640
0
}
1641