Coverage Report

Created: 2026-08-31 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsmraw/libsmraw/libsmraw_information_file.c
Line
Count
Source
1
/*
2
 * Information file functions
3
 *
4
 * Copyright (C) 2010-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <file_stream.h>
24
#include <memory.h>
25
#include <narrow_string.h>
26
#include <system_string.h>
27
#include <types.h>
28
#include <wide_string.h>
29
30
#include "libsmraw_definitions.h"
31
#include "libsmraw_information_file.h"
32
#include "libsmraw_libcerror.h"
33
#include "libsmraw_libfvalue.h"
34
35
/* Creates an information file
36
 * Make sure the value information_file is referencing, is set to NULL
37
 * Returns 1 if successful or -1 on error
38
 */
39
int libsmraw_information_file_initialize(
40
     libsmraw_information_file_t **information_file,
41
     libcerror_error_t **error )
42
0
{
43
0
  static char *function = "libsmraw_information_file_initialize";
44
45
0
  if( information_file == NULL )
46
0
  {
47
0
    libcerror_error_set(
48
0
     error,
49
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
50
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
51
0
     "%s: invalid information file.",
52
0
     function );
53
54
0
    return( -1 );
55
0
  }
56
0
  if( *information_file != NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
61
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
62
0
     "%s: invalid information file value already set.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
0
  *information_file = memory_allocate_structure(
68
0
                       libsmraw_information_file_t );
69
70
0
  if( *information_file == NULL )
71
0
  {
72
0
    libcerror_error_set(
73
0
     error,
74
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
75
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
76
0
     "%s: unable to create information file.",
77
0
     function );
78
79
0
    goto on_error;
80
0
  }
81
0
  if( memory_set(
82
0
       *information_file,
83
0
       0,
84
0
       sizeof( libsmraw_information_file_t ) ) == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
89
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
90
0
     "%s: unable to clear information file.",
91
0
     function );
92
93
0
    goto on_error;
94
0
  }
95
0
  return( 1 );
96
97
0
on_error:
98
0
  if( *information_file != NULL )
99
0
  {
100
0
    memory_free(
101
0
     *information_file );
102
103
0
    *information_file = NULL;
104
0
  }
105
0
  return( -1 );
106
0
}
107
108
/* Frees an information file
109
 * Returns 1 if successful or -1 on error
110
 */
111
int libsmraw_information_file_free(
112
     libsmraw_information_file_t **information_file,
113
     libcerror_error_t **error )
114
0
{
115
0
  static char *function = "libsmraw_information_file_free";
116
117
0
  if( information_file == NULL )
118
0
  {
119
0
    libcerror_error_set(
120
0
     error,
121
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
122
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
123
0
     "%s: invalid information file.",
124
0
     function );
125
126
0
    return( -1 );
127
0
  }
128
0
  if( *information_file != NULL )
129
0
  {
130
0
    if( ( *information_file )->name != NULL )
131
0
    {
132
0
      memory_free(
133
0
       ( *information_file )->name );
134
0
    }
135
0
    memory_free(
136
0
     *information_file );
137
138
0
    *information_file = NULL;
139
0
  }
140
0
  return( 1 );
141
0
}
142
143
/* Sets the filename
144
 * Returns 1 if successful or -1 on error
145
 */
146
int libsmraw_information_file_set_name(
147
     libsmraw_information_file_t *information_file,
148
     const system_character_t *name,
149
     size_t name_length,
150
     libcerror_error_t **error )
151
0
{
152
0
  static char *function = "libsmraw_information_file_set_name";
153
154
0
  if( information_file == NULL )
155
0
  {
156
0
    libcerror_error_set(
157
0
     error,
158
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
159
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
160
0
     "%s: invalid information file.",
161
0
     function );
162
163
0
    return( -1 );
164
0
  }
165
0
  if( name == NULL )
166
0
  {
167
0
    libcerror_error_set(
168
0
     error,
169
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
170
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
171
0
     "%s: invalid name.",
172
0
     function );
173
174
0
    return( -1 );
175
0
  }
176
0
  if( name_length > (size_t) SSIZE_MAX )
177
0
  {
178
0
    libcerror_error_set(
179
0
     error,
180
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
181
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
182
0
     "%s: invalid name length value exceeds maximum.",
183
0
     function );
184
185
0
    return( -1 );
186
0
  }
187
0
  information_file->name = system_string_allocate(
188
0
                            name_length + 1 );
189
190
0
  if( information_file->name == NULL )
191
0
  {
192
0
    libcerror_error_set(
193
0
     error,
194
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
195
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
196
0
     "%s: unable to allocate name.",
197
0
     function );
198
199
0
    return( -1 );
200
0
  }
201
0
  if( system_string_copy(
202
0
       information_file->name,
203
0
       name,
204
0
       name_length ) == NULL )
205
0
  {
206
0
    libcerror_error_set(
207
0
     error,
208
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
209
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
210
0
     "%s: unable to set name.",
211
0
     function );
212
213
0
    return( -1 );
214
0
  }
215
0
  information_file->name[ name_length ] = 0;
216
217
0
  information_file->name_size = name_length + 1;
218
219
0
  return( 1 );
220
0
}
221
222
/* Opens a information file
223
 * Returns 1 if successful or -1 on error
224
 */
225
int libsmraw_information_file_open(
226
     libsmraw_information_file_t *information_file,
227
     const system_character_t *filename,
228
     int access_flags,
229
     libcerror_error_t **error )
230
0
{
231
0
  const system_character_t *mode = NULL;
232
0
  static char *function          = "libsmraw_information_file_open";
233
234
0
  if( information_file == NULL )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
240
0
     "%s: invalid information file.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
0
  if( filename == NULL )
246
0
  {
247
0
    libcerror_error_set(
248
0
     error,
249
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
251
0
     "%s: invalid filename.",
252
0
     function );
253
254
0
    return( -1 );
255
0
  }
256
0
  if( information_file->file_stream != NULL )
257
0
  {
258
0
    libcerror_error_set(
259
0
     error,
260
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
262
0
     "%s: invalid information file - file stream already set.",
263
0
     function );
264
265
0
    return( -1 );
266
0
  }
267
0
  if( ( ( access_flags & LIBSMRAW_ACCESS_FLAG_READ ) == 0 )
268
0
   && ( ( access_flags & LIBSMRAW_ACCESS_FLAG_WRITE ) == 0 ) )
269
0
  {
270
0
    libcerror_error_set(
271
0
     error,
272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273
0
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
274
0
     "%s: unsupported access flags.",
275
0
     function );
276
277
0
    return( -1 );
278
0
  }
279
0
  if( ( access_flags & LIBSMRAW_ACCESS_FLAG_WRITE ) != 0 )
280
0
  {
281
0
    mode = (system_character_t *) FILE_STREAM_OPEN_WRITE;
282
0
  }
283
0
  else
284
0
  {
285
0
    mode = (system_character_t *) FILE_STREAM_OPEN_READ;
286
0
  }
287
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
288
  information_file->file_stream = file_stream_open_wide(
289
                                   filename,
290
                                   mode );
291
#else
292
0
  information_file->file_stream = file_stream_open(
293
0
                                   filename,
294
0
                                   mode );
295
0
#endif
296
297
0
  if( information_file->file_stream == NULL )
298
0
  {
299
0
    libcerror_error_set(
300
0
     error,
301
0
     LIBCERROR_ERROR_DOMAIN_IO,
302
0
     LIBCERROR_IO_ERROR_OPEN_FAILED,
303
0
     "%s: unable to open: %" PRIs_SYSTEM ".",
304
0
     function,
305
0
     filename );
306
307
0
    return( -1 );
308
0
  }
309
0
  return( 1 );
310
0
}
311
312
/* Closes the information file
313
 * Returns the 0 if successful or -1 on error
314
 */
315
int libsmraw_information_file_close(
316
     libsmraw_information_file_t *information_file,
317
     libcerror_error_t **error )
318
0
{
319
0
  static char *function = "libsmraw_information_file_close";
320
321
0
  if( information_file == NULL )
322
0
  {
323
0
    libcerror_error_set(
324
0
     error,
325
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
326
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
327
0
     "%s: invalid information file.",
328
0
     function );
329
330
0
    return( -1 );
331
0
  }
332
0
  if( information_file->name != NULL )
333
0
  {
334
0
    memory_free(
335
0
     information_file->name );
336
337
0
    information_file->name = NULL;
338
0
  }
339
0
  if( information_file->file_stream != NULL )
340
0
  {
341
0
    if( file_stream_close(
342
0
         information_file->file_stream ) != 0 )
343
0
    {
344
0
      libcerror_error_set(
345
0
       error,
346
0
       LIBCERROR_ERROR_DOMAIN_IO,
347
0
       LIBCERROR_IO_ERROR_CLOSE_FAILED,
348
0
       "%s: unable to close file stream.",
349
0
       function );
350
351
0
      return( -1 );
352
0
    }
353
0
    information_file->file_stream = NULL;
354
0
  }
355
0
  return( 0 );
356
0
}
357
358
/* Reads a section with its values from the information file
359
 * Returns the 1 if successful, 0 if no such section or -1 on error
360
 */
361
int libsmraw_information_file_read_section(
362
     libsmraw_information_file_t *information_file,
363
     const uint8_t *section_identifier,
364
     size_t section_identifier_length,
365
     libfvalue_table_t *values_table,
366
     libcerror_error_t **error )
367
0
{
368
0
  char input_string[ 128 ];
369
370
0
  libfvalue_value_t *value       = NULL;
371
0
  char *value_data               = NULL;
372
0
  char *value_identifier         = NULL;
373
0
  char *result_string            = NULL;
374
0
  static char *function          = "libsmraw_information_file_read_section";
375
0
  size_t input_string_index      = 0;
376
0
  size_t value_identifier_length = 0;
377
0
  size_t value_data_length       = 0;
378
0
  uint8_t in_section             = 0;
379
0
  int result                     = 0;
380
381
0
  if( information_file == NULL )
382
0
  {
383
0
    libcerror_error_set(
384
0
     error,
385
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
386
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
387
0
     "%s: invalid information file.",
388
0
     function );
389
390
0
    return( -1 );
391
0
  }
392
0
  if( information_file->file_stream == NULL )
393
0
  {
394
0
    libcerror_error_set(
395
0
     error,
396
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
397
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
398
0
     "%s: invalid information file - missing file stream.",
399
0
     function );
400
401
0
    return( -1 );
402
0
  }
403
0
  if( section_identifier == NULL )
404
0
  {
405
0
    libcerror_error_set(
406
0
     error,
407
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
408
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
409
0
     "%s: invalid section identifier.",
410
0
     function );
411
412
0
    return( -1 );
413
0
  }
414
0
  if( section_identifier_length > (size_t) SSIZE_MAX )
415
0
  {
416
0
    libcerror_error_set(
417
0
     error,
418
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
419
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
420
0
     "%s: invalid section identifier length value exceeds maximum.",
421
0
     function );
422
423
0
    return( -1 );
424
0
  }
425
  /* Reset the offset to start of the file stream
426
   */
427
0
  if( file_stream_seek_offset(
428
0
       information_file->file_stream,
429
0
       0,
430
0
       SEEK_SET ) != 0 )
431
0
  {
432
0
    libcerror_error_set(
433
0
     error,
434
0
     LIBCERROR_ERROR_DOMAIN_IO,
435
0
     LIBCERROR_IO_ERROR_SEEK_FAILED,
436
0
     "%s: unable to seek stream offset: 0.",
437
0
     function );
438
439
0
    return( -1 );
440
0
  }
441
0
  while( file_stream_at_end(
442
0
          information_file->file_stream ) == 0 )
443
0
  {
444
0
    result_string = file_stream_get_string(
445
0
                     information_file->file_stream,
446
0
                     input_string,
447
0
                     128 );
448
449
0
    if( result_string == NULL )
450
0
    {
451
0
      if( file_stream_at_end(
452
0
           information_file->file_stream ) != 0 )
453
0
      {
454
0
        break;
455
0
      }
456
0
      libcerror_error_set(
457
0
       error,
458
0
       LIBCERROR_ERROR_DOMAIN_IO,
459
0
       LIBCERROR_IO_ERROR_READ_FAILED,
460
0
       "%s: error reading string from file stream.",
461
0
       function );
462
463
0
      return( -1 );
464
0
    }
465
    /* Skip leading white space
466
     */
467
0
    for( input_string_index = 0;
468
0
         input_string_index < 128;
469
0
         input_string_index++ )
470
0
    {
471
0
      if( ( input_string[ input_string_index ] != '\t' )
472
0
       && ( input_string[ input_string_index ] != '\n' )
473
0
       && ( input_string[ input_string_index ] != '\f' )
474
0
       && ( input_string[ input_string_index ] != '\v' )
475
0
       && ( input_string[ input_string_index ] != '\r' )
476
0
       && ( input_string[ input_string_index ] != ' ' ) )
477
0
      {
478
0
        break;
479
0
      }
480
0
    }
481
    /* Skip an empty line
482
     */
483
0
    if( input_string[ input_string_index ] == 0 )
484
0
    {
485
0
      continue;
486
0
    }
487
0
    if( in_section != 0 )
488
0
    {
489
      /* Check for the end of the section
490
       */
491
0
      if( ( ( input_string_index + section_identifier_length + 2 ) < 128 )
492
0
       && ( input_string[ input_string_index ] == '<' )
493
0
       && ( input_string[ input_string_index + 1 ] == '/' )
494
0
       && ( narrow_string_compare(
495
0
             &( input_string[ input_string_index + 2 ] ),
496
0
             section_identifier,
497
0
             section_identifier_length ) == 0 )
498
0
       && ( input_string[ input_string_index + section_identifier_length + 2 ] == '>' ) )
499
0
      {
500
0
        result = 1;
501
502
0
        break;
503
0
      }
504
0
      if( input_string[ input_string_index ] == '<' )
505
0
      {
506
        /* Determine the value identifier
507
         */
508
0
        input_string_index++;
509
510
0
        value_identifier        = &( input_string[ input_string_index ] );
511
0
        value_identifier_length = 0;
512
513
0
        while( input_string_index < 128 )
514
0
        {
515
0
          if( ( ( input_string[ input_string_index ] >= 'A' )
516
0
            &&  ( input_string[ input_string_index ] <= 'I' ) )
517
0
           || ( ( input_string[ input_string_index ] >= 'J' )
518
0
            &&  ( input_string[ input_string_index ] <= 'R' ) )
519
0
           || ( ( input_string[ input_string_index ] >= 'S' )
520
0
            &&  ( input_string[ input_string_index ] <= 'Z' ) )
521
0
           || ( ( input_string[ input_string_index ] >= 'a' )
522
0
            &&  ( input_string[ input_string_index ] <= 'i' ) )
523
0
           || ( ( input_string[ input_string_index ] >= 'j' )
524
0
            &&  ( input_string[ input_string_index ] <= 'r' ) )
525
0
           || ( ( input_string[ input_string_index ] >= 's' )
526
0
            &&  ( input_string[ input_string_index ] <= 'z' ) )
527
0
           || ( ( input_string[ input_string_index ] >= '0' )
528
0
            &&  ( input_string[ input_string_index ] <= '9' ) )
529
0
           ||   ( input_string[ input_string_index ] == '_' ) )
530
0
          {
531
0
            value_identifier_length++;
532
0
          }
533
0
          else
534
0
          {
535
0
            break;
536
0
          }
537
0
          input_string_index++;
538
0
        }
539
0
        if( input_string_index >= 128 )
540
0
        {
541
0
          break;
542
0
        }
543
        /* Check if there is a supported value identifier
544
         */
545
0
        if( input_string[ input_string_index ] != '>' )
546
0
        {
547
0
          continue;
548
0
        }
549
        /* Make sure the value identifier is terminated by an end of string character
550
         */
551
0
        input_string[ input_string_index ] = 0;
552
553
        /* Determine the value
554
         */
555
0
        input_string_index++;
556
557
0
        value_data        = &( input_string[ input_string_index ] );
558
0
        value_data_length = 0;
559
560
0
        while( input_string_index < 128 )
561
0
        {
562
0
          if( ( input_string[ input_string_index ] == 0 )
563
0
           || ( input_string[ input_string_index ] == '<' ) )
564
0
          {
565
0
            break;
566
0
          }
567
0
          value_data_length++;
568
569
0
          input_string_index++;
570
0
        }
571
0
        if( input_string_index >= 128 )
572
0
        {
573
0
          break;
574
0
        }
575
        /* Check if there is a supported value
576
         */
577
0
        if( input_string[ input_string_index ] != '<' )
578
0
        {
579
0
          continue;
580
0
        }
581
        /* Make sure the value data is terminated by an end of string
582
         */
583
0
        input_string[ input_string_index ] = 0;
584
585
        /* Check the value identifier
586
         */
587
0
        input_string_index++;
588
589
0
        if( ( ( input_string_index + value_identifier_length + 2 ) >= 128 )
590
0
         || ( input_string[ input_string_index ] != '/' )
591
0
         || ( narrow_string_compare(
592
0
               &( input_string[ input_string_index + 1 ] ),
593
0
               value_identifier,
594
0
               value_identifier_length ) != 0 )
595
0
         || ( input_string[ input_string_index + value_identifier_length + 1 ] != '>' ) )
596
0
        {
597
0
          continue;
598
0
        }
599
0
        if( libfvalue_value_type_initialize(
600
0
             &value,
601
0
             LIBFVALUE_VALUE_TYPE_STRING_UTF8,
602
0
             error ) != 1 )
603
0
        {
604
0
          libcerror_error_set(
605
0
           error,
606
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
607
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
608
0
           "%s: unable to create value: %s.",
609
0
           function,
610
0
           value_identifier );
611
612
0
          goto on_error;
613
0
        }
614
0
        if( libfvalue_value_set_identifier(
615
0
             value,
616
0
             (uint8_t *) value_identifier,
617
0
             value_identifier_length,
618
0
             LIBFVALUE_VALUE_IDENTIFIER_FLAG_MANAGED,
619
0
             error ) != 1 )
620
0
        {
621
0
          libcerror_error_set(
622
0
           error,
623
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
624
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
625
0
           "%s: unable to set identifier in value: %d.",
626
0
           function,
627
0
           value_identifier );
628
629
0
          goto on_error;
630
0
        }
631
0
        if( libfvalue_value_set_data(
632
0
             value,
633
0
             (uint8_t *) value_data,
634
0
             value_data_length + 1,
635
0
             LIBFVALUE_ENDIAN_NATIVE,
636
0
             LIBFVALUE_VALUE_FLAG_DATA_MANAGED,
637
0
             error ) != 1 )
638
0
        {
639
0
          libcerror_error_set(
640
0
           error,
641
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
642
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
643
0
           "%s: unable to set value: %s data.",
644
0
           function,
645
0
           value_identifier );
646
647
0
          goto on_error;
648
0
        }
649
0
        if( libfvalue_table_set_value(
650
0
             values_table,
651
0
             value,
652
0
             error ) != 1 )
653
0
        {
654
0
          libcerror_error_set(
655
0
           error,
656
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
657
0
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
658
0
           "%s: unable to set value: %s in values table.",
659
0
           function,
660
0
           value_identifier );
661
662
0
          goto on_error;
663
0
        }
664
0
        value = NULL;
665
0
      }
666
0
    }
667
0
    else
668
0
    {
669
      /* Check for the start of the section
670
       */
671
0
      if( ( ( input_string_index + section_identifier_length + 1 ) < 128 )
672
0
       && ( input_string[ input_string_index ] == '<' )
673
0
       && ( narrow_string_compare(
674
0
             &( input_string[ input_string_index + 1 ] ),
675
0
             section_identifier,
676
0
             section_identifier_length ) == 0 )
677
0
       && ( input_string[ input_string_index + section_identifier_length + 1 ] == '>' ) )
678
0
      {
679
0
        in_section = 1;
680
0
      }
681
0
    }
682
0
  }
683
0
  return( result );
684
685
0
on_error:
686
0
  if( value != NULL )
687
0
  {
688
0
    libfvalue_value_free(
689
0
     &value,
690
0
     NULL );
691
0
  }
692
0
  return( -1 );
693
0
}
694
695
/* Write a section with its values to the information file
696
 * Returns the 1 if successful or -1 on error
697
 */
698
int libsmraw_information_file_write_section(
699
     libsmraw_information_file_t *information_file,
700
     const uint8_t *section_identifier,
701
     size_t section_identifier_length,
702
     libfvalue_table_t *values_table,
703
     libcerror_error_t **error )
704
0
{
705
0
  libfvalue_value_t *value = NULL;
706
0
  static char *function    = "libsmraw_information_file_write_section";
707
0
  ssize_t write_count      = 0;
708
0
  int number_of_values     = 0;
709
0
  int print_count          = 0;
710
0
  int result               = 1;
711
0
  int value_iterator       = 0;
712
713
0
  if( information_file == NULL )
714
0
  {
715
0
    libcerror_error_set(
716
0
     error,
717
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
718
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
719
0
     "%s: invalid information file.",
720
0
     function );
721
722
0
    return( -1 );
723
0
  }
724
0
  if( information_file->file_stream == NULL )
725
0
  {
726
0
    libcerror_error_set(
727
0
     error,
728
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
729
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
730
0
     "%s: invalid information file - missing file stream.",
731
0
     function );
732
733
0
    return( -1 );
734
0
  }
735
0
  if( section_identifier == NULL )
736
0
  {
737
0
    libcerror_error_set(
738
0
     error,
739
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
740
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
741
0
     "%s: invalid section identifier.",
742
0
     function );
743
744
0
    return( -1 );
745
0
  }
746
0
  if( section_identifier_length > (size_t) SSIZE_MAX )
747
0
  {
748
0
    libcerror_error_set(
749
0
     error,
750
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
751
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
752
0
     "%s: invalid section identifier length value exceeds maximum.",
753
0
     function );
754
755
0
    return( -1 );
756
0
  }
757
0
  if( values_table == NULL )
758
0
  {
759
0
    libcerror_error_set(
760
0
     error,
761
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
762
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
763
0
     "%s: invalid values table.",
764
0
     function );
765
766
0
    return( -1 );
767
0
  }
768
  /* Write section start
769
   */
770
0
  print_count = fprintf(
771
0
                 information_file->file_stream,
772
0
                 "<%s>\n",
773
0
                 section_identifier );
774
775
0
  if( ( print_count < 0 )
776
0
   || ( (size_t) print_count > ( section_identifier_length + 3 ) ) )
777
0
  {
778
0
    libcerror_error_set(
779
0
     error,
780
0
     LIBCERROR_ERROR_DOMAIN_IO,
781
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
782
0
     "%s: unable to write section start to file stream.",
783
0
     function );
784
785
0
    return( -1 );
786
0
  }
787
  /* Write section values
788
   */
789
0
  if( libfvalue_table_get_number_of_values(
790
0
       values_table,
791
0
       &number_of_values,
792
0
       error ) != 1 )
793
0
  {
794
0
    libcerror_error_set(
795
0
     error,
796
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
797
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
798
0
     "%s: unable to retrieve number of values.",
799
0
     function );
800
801
0
    return( -1 );
802
0
  }
803
0
  for( value_iterator = 0;
804
0
       value_iterator < number_of_values;
805
0
       value_iterator++ )
806
0
  {
807
0
    print_count = fprintf(
808
0
             information_file->file_stream,
809
0
             "\t" );
810
811
0
    if( ( print_count < 0 )
812
0
     || ( (size_t) print_count > 1 ) )
813
0
    {
814
0
      libcerror_error_set(
815
0
       error,
816
0
       LIBCERROR_ERROR_DOMAIN_IO,
817
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
818
0
       "%s: unable to write to file stream.",
819
0
       function );
820
821
0
      return( -1 );
822
0
    }
823
0
    if( libfvalue_table_get_value_by_index(
824
0
         values_table,
825
0
         value_iterator,
826
0
         &value,
827
0
         error ) != 1 )
828
0
    {
829
0
      libcerror_error_set(
830
0
       error,
831
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
832
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
833
0
       "%s: unable to retrieve value: %d from values table.",
834
0
       function,
835
0
       value_iterator );
836
837
0
      result = -1;
838
839
0
      continue;
840
0
    }
841
0
    write_count = libfvalue_value_write_to_file_stream(
842
0
                   value,
843
0
                   information_file->file_stream,
844
0
                   error );
845
846
0
    if( write_count <= 0 )
847
0
    {
848
0
      libcerror_error_set(
849
0
       error,
850
0
       LIBCERROR_ERROR_DOMAIN_IO,
851
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
852
0
       "%s: unable to write value: %d to file stream.",
853
0
       function,
854
0
       value_iterator );
855
856
0
      result = -1;
857
0
    }
858
0
    print_count = fprintf(
859
0
             information_file->file_stream,
860
0
             "\n" );
861
862
0
    if( ( print_count < 0 )
863
0
     || ( (size_t) print_count > 1 ) )
864
0
    {
865
0
      libcerror_error_set(
866
0
       error,
867
0
       LIBCERROR_ERROR_DOMAIN_IO,
868
0
       LIBCERROR_IO_ERROR_WRITE_FAILED,
869
0
       "%s: unable to write to file stream.",
870
0
       function );
871
872
0
      return( -1 );
873
0
    }
874
0
  }
875
  /* Write section end
876
   */
877
0
  print_count = fprintf(
878
0
                 information_file->file_stream,
879
0
                 "</%s>\n\n",
880
0
                 section_identifier );
881
882
0
  if( ( print_count < 0 )
883
0
   || ( (size_t) print_count > ( section_identifier_length + 5 ) ) )
884
0
  {
885
0
    libcerror_error_set(
886
0
     error,
887
0
     LIBCERROR_ERROR_DOMAIN_IO,
888
0
     LIBCERROR_IO_ERROR_WRITE_FAILED,
889
0
     "%s: unable to write section end to file stream.",
890
0
     function );
891
892
0
    return( -1 );
893
0
  }
894
0
  return( result );
895
0
}
896