Coverage Report

Created: 2026-10-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfwsi/libfwsi/libfwsi_acronis_tib_file_values.c
Line
Count
Source
1
/*
2
 * Acronis True Image (TIB) file (shell item) values 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 <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfwsi_acronis_tib_file_values.h"
28
#include "libfwsi_debug.h"
29
#include "libfwsi_definitions.h"
30
#include "libfwsi_libcerror.h"
31
#include "libfwsi_libcnotify.h"
32
#include "libfwsi_libfdatetime.h"
33
#include "libfwsi_libuna.h"
34
#include "libfwsi_unused.h"
35
36
/* Creates compressed folder values
37
 * Make sure the value acronis_tib_file_values is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfwsi_acronis_tib_file_values_initialize(
41
     libfwsi_acronis_tib_file_values_t **acronis_tib_file_values,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function = "libfwsi_acronis_tib_file_values_initialize";
45
46
0
  if( acronis_tib_file_values == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid compressed folder values.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
0
  if( *acronis_tib_file_values != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid compressed folder values value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  *acronis_tib_file_values = memory_allocate_structure(
69
0
                              libfwsi_acronis_tib_file_values_t );
70
71
0
  if( *acronis_tib_file_values == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create compressed folder values.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
0
  if( memory_set(
83
0
       *acronis_tib_file_values,
84
0
       0,
85
0
       sizeof( libfwsi_acronis_tib_file_values_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear compressed folder values.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
0
  return( 1 );
97
98
0
on_error:
99
0
  if( *acronis_tib_file_values != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *acronis_tib_file_values );
103
104
0
    *acronis_tib_file_values = NULL;
105
0
  }
106
0
  return( -1 );
107
0
}
108
109
/* Frees compressed folder values
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfwsi_acronis_tib_file_values_free(
113
     libfwsi_acronis_tib_file_values_t **acronis_tib_file_values,
114
     libcerror_error_t **error )
115
0
{
116
0
  static char *function = "libfwsi_acronis_tib_file_values_free";
117
118
0
  if( acronis_tib_file_values == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid compressed folder values.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
0
  if( *acronis_tib_file_values != NULL )
130
0
  {
131
0
    memory_free(
132
0
     *acronis_tib_file_values );
133
134
0
    *acronis_tib_file_values = NULL;
135
0
  }
136
0
  return( 1 );
137
0
}
138
139
/* Reads the compressed folder values
140
 * Returns 1 if successful, 0 if not supported or -1 on error
141
 */
142
int libfwsi_acronis_tib_file_values_read_data(
143
     libfwsi_acronis_tib_file_values_t *acronis_tib_file_values,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
0
{
148
0
  static char *function     = "libfwsi_acronis_tib_file_values_read_data";
149
0
  size_t data_offset        = 0;
150
0
  uint32_t string_data_size = 0;
151
152
#if defined( HAVE_DEBUG_OUTPUT )
153
  uint64_t value_64bit      = 0;
154
  uint32_t value_32bit      = 0;
155
  uint16_t value_16bit      = 0;
156
#endif
157
158
0
  if( acronis_tib_file_values == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid compressed folder values.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
0
  if( data == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid data.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
0
  if( data_size > (size_t) SSIZE_MAX )
181
0
  {
182
0
    libcerror_error_set(
183
0
     error,
184
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
185
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
186
0
     "%s: data size exceeds maximum.",
187
0
     function );
188
189
0
    return( -1 );
190
0
  }
191
  /* Do not try to parse unsupported data sizes
192
   */
193
0
  if( data_size < 50 )
194
0
  {
195
0
    return( 0 );
196
0
  }
197
  /* Do not try to parse unsupported data
198
   */
199
0
  if( ( data[ 2 ] != 0x52 )
200
0
   || ( data[ 3 ] != 0x67 )
201
0
   || ( data[ 4 ] != 0xb1 )
202
0
   || ( data[ 5 ] != 0xac ) )
203
0
  {
204
0
    return( 0 );
205
0
  }
206
0
  byte_stream_copy_to_uint32_little_endian(
207
0
   &( data[ data_offset ] ),
208
0
   string_data_size );
209
210
#if defined( HAVE_DEBUG_OUTPUT )
211
  if( libcnotify_verbose != 0 )
212
  {
213
    libcnotify_printf(
214
     "%s: unknown1\t\t\t\t: 0x%02" PRIx8 "\n",
215
     function,
216
     data[ 3 ] );
217
218
    byte_stream_copy_to_uint16_little_endian(
219
     &( data[ 4 ] ),
220
     value_16bit );
221
    libcnotify_printf(
222
     "%s: unknown2\t\t\t\t: 0x%04" PRIx16 "\n",
223
     function,
224
     value_16bit );
225
226
    byte_stream_copy_to_uint32_little_endian(
227
     &( data[ 6 ] ),
228
     value_32bit );
229
    libcnotify_printf(
230
     "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
231
     function,
232
     value_32bit );
233
234
    byte_stream_copy_to_uint64_little_endian(
235
     &( data[ 10 ] ),
236
     value_64bit );
237
    libcnotify_printf(
238
     "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
239
     function,
240
     value_64bit );
241
242
    byte_stream_copy_to_uint32_little_endian(
243
     &( data[ 18 ] ),
244
     value_32bit );
245
    libcnotify_printf(
246
     "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
247
     function,
248
     value_32bit );
249
250
    byte_stream_copy_to_uint32_little_endian(
251
     &( data[ 22 ] ),
252
     value_32bit );
253
    libcnotify_printf(
254
     "%s: unknown6\t\t\t\t: 0x%08" PRIx32 "\n",
255
     function,
256
     value_32bit );
257
258
    if( libfwsi_debug_print_fat_date_time_value(
259
         function,
260
         "unknown time1\t\t\t",
261
         &( data[ 26 ] ),
262
         4,
263
         LIBFDATETIME_ENDIAN_LITTLE,
264
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
265
         error ) != 1 )
266
    {
267
      libcerror_error_set(
268
       error,
269
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
270
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
271
       "%s: unable to print FAT date time value.",
272
       function );
273
274
      return( -1 );
275
    }
276
    byte_stream_copy_to_uint32_little_endian(
277
     &( data[ 30 ] ),
278
     value_32bit );
279
    libcnotify_printf(
280
     "%s: unknown7\t\t\t\t: 0x%08" PRIx32 "\n",
281
     function,
282
     value_32bit );
283
284
    if( libfwsi_debug_print_fat_date_time_value(
285
         function,
286
         "unknown time2\t\t\t",
287
         &( data[ 34 ] ),
288
         4,
289
         LIBFDATETIME_ENDIAN_LITTLE,
290
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
291
         error ) != 1 )
292
    {
293
      libcerror_error_set(
294
       error,
295
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
296
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
297
       "%s: unable to print FAT date time value.",
298
       function );
299
300
      return( -1 );
301
    }
302
    byte_stream_copy_to_uint64_little_endian(
303
     &( data[ 38 ] ),
304
     value_64bit );
305
    libcnotify_printf(
306
     "%s: unknown8\t\t\t\t: 0x%08" PRIx64 "\n",
307
     function,
308
     value_64bit );
309
310
    libcnotify_printf(
311
     "%s: string1 data size\t\t: %" PRIu32 "\n",
312
     function,
313
     string_data_size );
314
  }
315
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
316
317
0
  data_offset = 50;
318
319
0
  if( string_data_size > ( ( data_size - data_offset ) / 2 ) )
320
0
  {
321
0
    libcerror_error_set(
322
0
     error,
323
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
324
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
325
0
     "%s: invalid string1 data size value out of bounds.",
326
0
     function );
327
328
0
    return( -1 );
329
0
  }
330
0
  string_data_size *= 2;
331
332
0
  if( string_data_size > 0 )
333
0
  {
334
#if defined( HAVE_DEBUG_OUTPUT )
335
    if( libcnotify_verbose != 0 )
336
    {
337
      if( libfwsi_debug_print_utf16_string_value(
338
           function,
339
           "string1\t\t\t\t",
340
           &( data[ data_offset ] ),
341
           string_data_size,
342
           LIBUNA_ENDIAN_LITTLE,
343
           error ) != 1 )
344
      {
345
        libcerror_error_set(
346
         error,
347
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
348
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
349
         "%s: unable to print UTF-16 string value.",
350
         function );
351
352
        return( -1 );
353
      }
354
    }
355
#endif
356
0
    data_offset += string_data_size;
357
0
  }
358
0
  if( data_offset >= ( data_size - 4 ) )
359
0
  {
360
0
    libcerror_error_set(
361
0
     error,
362
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
363
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
364
0
     "%s: invalid data size value out of bounds.",
365
0
     function );
366
367
0
    return( -1 );
368
0
  }
369
0
  byte_stream_copy_to_uint32_little_endian(
370
0
   &( data[ data_offset ] ),
371
0
   string_data_size );
372
373
#if defined( HAVE_DEBUG_OUTPUT )
374
  if( libcnotify_verbose != 0 )
375
  {
376
    libcnotify_printf(
377
     "%s: string2 data size\t\t: %" PRIu32 "\n",
378
     function,
379
     string_data_size );
380
  }
381
#endif
382
0
  data_offset += 4;
383
384
0
  if( string_data_size > ( ( data_size - data_offset ) / 2 ) )
385
0
  {
386
0
    libcerror_error_set(
387
0
     error,
388
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
389
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
390
0
     "%s: invalid string2 data size value out of bounds.",
391
0
     function );
392
393
0
    return( -1 );
394
0
  }
395
0
  string_data_size *= 2;
396
397
0
  if( string_data_size > 0 )
398
0
  {
399
#if defined( HAVE_DEBUG_OUTPUT )
400
    if( libcnotify_verbose != 0 )
401
    {
402
      if( libfwsi_debug_print_utf16_string_value(
403
           function,
404
           "string2\t\t\t\t",
405
           &( data[ data_offset ] ),
406
           string_data_size,
407
           LIBUNA_ENDIAN_LITTLE,
408
           error ) != 1 )
409
      {
410
        libcerror_error_set(
411
         error,
412
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
413
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
414
         "%s: unable to print UTF-16 string value.",
415
         function );
416
417
        return( -1 );
418
      }
419
    }
420
#endif
421
0
    data_offset += string_data_size;
422
0
  }
423
0
  if( data_offset >= ( data_size - 4 ) )
424
0
  {
425
0
    libcerror_error_set(
426
0
     error,
427
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
428
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
429
0
     "%s: invalid data size value out of bounds.",
430
0
     function );
431
432
0
    return( -1 );
433
0
  }
434
0
  byte_stream_copy_to_uint32_little_endian(
435
0
   &( data[ data_offset ] ),
436
0
   string_data_size );
437
438
#if defined( HAVE_DEBUG_OUTPUT )
439
  if( libcnotify_verbose != 0 )
440
  {
441
    libcnotify_printf(
442
     "%s: string3 data size\t\t: %" PRIu32 "\n",
443
     function,
444
     string_data_size );
445
  }
446
#endif
447
0
  data_offset += 4;
448
449
0
  if( string_data_size > ( ( data_size - data_offset ) / 2 ) )
450
0
  {
451
0
    libcerror_error_set(
452
0
     error,
453
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
454
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
455
0
     "%s: invalid string3 data size value out of bounds.",
456
0
     function );
457
458
0
    return( -1 );
459
0
  }
460
0
  string_data_size *= 2;
461
462
0
  if( string_data_size > 0 )
463
0
  {
464
#if defined( HAVE_DEBUG_OUTPUT )
465
    if( libcnotify_verbose != 0 )
466
    {
467
      if( libfwsi_debug_print_utf16_string_value(
468
           function,
469
           "string3\t\t\t\t",
470
           &( data[ data_offset ] ),
471
           string_data_size,
472
           LIBUNA_ENDIAN_LITTLE,
473
           error ) != 1 )
474
      {
475
        libcerror_error_set(
476
         error,
477
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
478
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
479
         "%s: unable to print UTF-16 string value.",
480
         function );
481
482
        return( -1 );
483
      }
484
    }
485
#endif
486
0
    data_offset += string_data_size;
487
0
  }
488
0
  if( data_offset >= ( data_size - 4 ) )
489
0
  {
490
0
    libcerror_error_set(
491
0
     error,
492
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
493
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
494
0
     "%s: invalid data size value out of bounds.",
495
0
     function );
496
497
0
    return( -1 );
498
0
  }
499
0
  byte_stream_copy_to_uint32_little_endian(
500
0
   &( data[ data_offset ] ),
501
0
   string_data_size );
502
503
#if defined( HAVE_DEBUG_OUTPUT )
504
  if( libcnotify_verbose != 0 )
505
  {
506
    libcnotify_printf(
507
     "%s: string4 data size\t\t: %" PRIu32 "\n",
508
     function,
509
     string_data_size );
510
  }
511
#endif
512
0
  data_offset += 4;
513
514
0
  if( string_data_size > ( ( data_size - data_offset ) / 2 ) )
515
0
  {
516
0
    libcerror_error_set(
517
0
     error,
518
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
519
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
520
0
     "%s: invalid string4 data size value out of bounds.",
521
0
     function );
522
523
0
    return( -1 );
524
0
  }
525
0
  string_data_size *= 2;
526
527
0
  if( string_data_size > 0 )
528
0
  {
529
#if defined( HAVE_DEBUG_OUTPUT )
530
    if( libcnotify_verbose != 0 )
531
    {
532
      if( libfwsi_debug_print_utf16_string_value(
533
           function,
534
           "string4\t\t\t\t",
535
           &( data[ data_offset ] ),
536
           string_data_size,
537
           LIBUNA_ENDIAN_LITTLE,
538
           error ) != 1 )
539
      {
540
        libcerror_error_set(
541
         error,
542
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
543
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
544
         "%s: unable to print UTF-16 string value.",
545
         function );
546
547
        return( -1 );
548
      }
549
    }
550
#endif
551
0
  }
552
#if defined( HAVE_DEBUG_OUTPUT )
553
  if( libcnotify_verbose != 0 )
554
  {
555
    libcnotify_printf(
556
     "\n" );
557
  }
558
#endif
559
0
  return( 1 );
560
0
}
561