Coverage Report

Created: 2024-02-25 07:20

/src/libftxf/libfusn/libfusn_record.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Record functions
3
 *
4
 * Copyright (C) 2011-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <narrow_string.h>
26
#include <system_string.h>
27
#include <types.h>
28
#include <wide_string.h>
29
30
#include "libfusn_debug.h"
31
#include "libfusn_libcerror.h"
32
#include "libfusn_libcnotify.h"
33
#include "libfusn_libfdatetime.h"
34
#include "libfusn_libuna.h"
35
#include "libfusn_record.h"
36
37
#include "fusn_record.h"
38
39
/* Creates a record
40
 * Make sure the value record is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfusn_record_initialize(
44
     libfusn_record_t **record,
45
     libcerror_error_t **error )
46
892
{
47
892
  libfusn_internal_record_t *internal_record = NULL;
48
892
  static char *function                      = "libfusn_record_initialize";
49
50
892
  if( record == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid record.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
892
  if( *record != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid record value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
892
  internal_record = memory_allocate_structure(
73
892
         libfusn_internal_record_t );
74
75
892
  if( internal_record == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create record.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
892
  if( memory_set(
87
892
       internal_record,
88
892
       0,
89
892
       sizeof( libfusn_internal_record_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear record.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
892
  *record = (libfusn_record_t *) internal_record;
101
102
892
  return( 1 );
103
104
0
on_error:
105
0
  if( internal_record != NULL )
106
0
  {
107
0
    memory_free(
108
0
     internal_record );
109
0
  }
110
0
  return( -1 );
111
892
}
112
113
/* Frees a record
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfusn_record_free(
117
     libfusn_record_t **record,
118
     libcerror_error_t **error )
119
892
{
120
892
  libfusn_internal_record_t *internal_record = NULL;
121
892
  static char *function                      = "libfusn_record_free";
122
123
892
  if( record == NULL )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
129
0
     "%s: invalid record.",
130
0
     function );
131
132
0
    return( -1 );
133
0
  }
134
892
  if( *record != NULL )
135
892
  {
136
892
    internal_record = (libfusn_internal_record_t *) *record;
137
892
    *record         = NULL;
138
139
892
    if( internal_record->name != NULL )
140
228
    {
141
228
      memory_free(
142
228
       internal_record->name );
143
228
    }
144
892
    memory_free(
145
892
     internal_record );
146
892
  }
147
892
  return( 1 );
148
892
}
149
150
/* Copies the record from the byte stream
151
 * Returns 1 if successful or -1 on error
152
 */
153
int libfusn_record_copy_from_byte_stream(
154
     libfusn_record_t *record,
155
     const uint8_t *byte_stream,
156
     size_t byte_stream_size,
157
     libcerror_error_t **error )
158
892
{
159
892
  libfusn_internal_record_t *internal_record = NULL;
160
892
  static char *function                      = "libfusn_record_copy_from_byte_stream";
161
892
  size_t byte_stream_offset                  = 0;
162
892
  uint16_t name_offset                       = 0;
163
892
  uint16_t name_size                         = 0;
164
165
#if defined( HAVE_DEBUG_OUTPUT )
166
  uint32_t value_32bit                       = 0;
167
#endif
168
169
892
  if( record == 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 record.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
892
  internal_record = (libfusn_internal_record_t *) record;
181
182
892
  if( internal_record->name != NULL )
183
0
  {
184
0
    libcerror_error_set(
185
0
     error,
186
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
187
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
188
0
     "%s: invalid record - name value already set.",
189
0
     function );
190
191
0
    return( -1 );
192
0
  }
193
892
  if( byte_stream == NULL )
194
0
  {
195
0
    libcerror_error_set(
196
0
     error,
197
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
198
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
199
0
     "%s: invalid byte stream.",
200
0
     function );
201
202
0
    return( -1 );
203
0
  }
204
892
  if( byte_stream_size > (size_t) SSIZE_MAX )
205
33
  {
206
33
    libcerror_error_set(
207
33
     error,
208
33
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
209
33
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
210
33
     "%s: invalid byte stream size value exceeds maximum.",
211
33
     function );
212
213
33
    return( -1 );
214
33
  }
215
859
  if( byte_stream_size < sizeof( fusn_record_header_t ) )
216
31
  {
217
31
    libcerror_error_set(
218
31
     error,
219
31
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220
31
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
221
31
     "%s: invalid byte stream value too small.",
222
31
     function );
223
224
31
    return( -1 );
225
31
  }
226
#if defined( HAVE_DEBUG_OUTPUT )
227
  if( libcnotify_verbose != 0 )
228
  {
229
    libcnotify_printf(
230
     "%s: record header data:\n",
231
     function );
232
    libcnotify_print_data(
233
     byte_stream,
234
     sizeof( fusn_record_header_t ),
235
     0 );
236
  }
237
#endif
238
828
  byte_stream_copy_to_uint32_little_endian(
239
828
   ( (fusn_record_header_t *) byte_stream )->record_size,
240
828
   internal_record->size );
241
242
828
  byte_stream_copy_to_uint16_little_endian(
243
828
   ( (fusn_record_header_t *) byte_stream )->major_version,
244
828
   internal_record->major_version );
245
246
828
  byte_stream_copy_to_uint16_little_endian(
247
828
   ( (fusn_record_header_t *) byte_stream )->minor_version,
248
828
   internal_record->minor_version );
249
250
828
  byte_stream_copy_to_uint64_little_endian(
251
828
   ( (fusn_record_header_t *) byte_stream )->update_time,
252
828
   internal_record->update_time );
253
254
828
  byte_stream_copy_to_uint64_little_endian(
255
828
   ( (fusn_record_header_t *) byte_stream )->file_reference,
256
828
   internal_record->file_reference );
257
258
828
  byte_stream_copy_to_uint32_little_endian(
259
828
   ( (fusn_record_header_t *) byte_stream )->file_attribute_flags,
260
828
   internal_record->file_attribute_flags );
261
262
828
  byte_stream_copy_to_uint64_little_endian(
263
828
   ( (fusn_record_header_t *) byte_stream )->parent_file_reference,
264
828
   internal_record->parent_file_reference );
265
266
828
  byte_stream_copy_to_uint64_little_endian(
267
828
   ( (fusn_record_header_t *) byte_stream )->update_sequence_number,
268
828
   internal_record->update_sequence_number );
269
270
828
  byte_stream_copy_to_uint32_little_endian(
271
828
   ( (fusn_record_header_t *) byte_stream )->update_reason_flags,
272
828
   internal_record->update_reason_flags );
273
274
828
  byte_stream_copy_to_uint32_little_endian(
275
828
   ( (fusn_record_header_t *) byte_stream )->update_source_flags,
276
828
   internal_record->update_source_flags );
277
278
828
  byte_stream_copy_to_uint16_little_endian(
279
828
   ( (fusn_record_header_t *) byte_stream )->name_size,
280
828
   name_size );
281
282
828
  byte_stream_copy_to_uint16_little_endian(
283
828
   ( (fusn_record_header_t *) byte_stream )->name_offset,
284
828
   name_offset );
285
286
#if defined( HAVE_DEBUG_OUTPUT )
287
  if( libcnotify_verbose != 0 )
288
  {
289
    libcnotify_printf(
290
     "%s: record size\t\t\t: %" PRIu32 "\n",
291
     function,
292
     internal_record->size );
293
294
    libcnotify_printf(
295
     "%s: major version\t\t\t: %" PRIu16 "\n",
296
     function,
297
     internal_record->major_version );
298
299
    libcnotify_printf(
300
     "%s: minor version\t\t\t: %" PRIu16 "\n",
301
     function,
302
     internal_record->minor_version );
303
304
    libcnotify_printf(
305
     "%s: file reference\t\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n",
306
     function,
307
     internal_record->file_reference & 0xffffffffffffUL,
308
     internal_record->file_reference >> 48 );
309
310
    libcnotify_printf(
311
     "%s: parent file reference\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n",
312
     function,
313
     internal_record->parent_file_reference & 0xffffffffffffUL,
314
     internal_record->parent_file_reference >> 48 );
315
316
    libcnotify_printf(
317
     "%s: update sequence number\t\t: 0x%08" PRIx64 "\n",
318
     function,
319
     internal_record->update_sequence_number );
320
321
    if( libfusn_debug_print_filetime_value(
322
         function,
323
         "update time\t\t\t",
324
         ( (fusn_record_header_t *) byte_stream )->update_time,
325
         8,
326
         LIBFDATETIME_ENDIAN_LITTLE,
327
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
328
         error ) != 1 )
329
    {
330
      libcerror_error_set(
331
       error,
332
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
334
       "%s: unable to print FILETIME value.",
335
       function );
336
337
      goto on_error;
338
    }
339
    libcnotify_printf(
340
     "%s: update reason flags\t\t: 0x%08" PRIx32 "\n",
341
     function,
342
     internal_record->update_reason_flags );
343
    libfusn_debug_print_update_reason_flags(
344
     internal_record->update_reason_flags );
345
    libcnotify_printf(
346
     "\n" );
347
348
    libcnotify_printf(
349
     "%s: update source flags\t\t: 0x%08" PRIx32 "\n",
350
     function,
351
     internal_record->update_source_flags );
352
    libfusn_debug_print_update_source_flags(
353
     internal_record->update_source_flags );
354
    libcnotify_printf(
355
     "\n" );
356
357
    byte_stream_copy_to_uint32_little_endian(
358
     ( (fusn_record_header_t *) byte_stream )->security_identifier_index,
359
     value_32bit );
360
    libcnotify_printf(
361
     "%s: security identifier index\t\t: %" PRIu32 "\n",
362
     function,
363
     value_32bit );
364
365
    libcnotify_printf(
366
     "%s: file attribute flags\t\t: 0x%08" PRIx32 "\n",
367
     function,
368
     internal_record->file_attribute_flags );
369
    libfusn_debug_print_file_attribute_flags(
370
     internal_record->file_attribute_flags );
371
    libcnotify_printf(
372
     "\n" );
373
374
    libcnotify_printf(
375
     "%s: name size\t\t\t\t: %" PRIu16 "\n",
376
     function,
377
     name_size );
378
379
    libcnotify_printf(
380
     "%s: name offset\t\t\t: %" PRIu16 "\n",
381
     function,
382
     name_offset );
383
  }
384
#endif
385
828
  byte_stream_offset = sizeof( fusn_record_header_t );
386
387
828
  if( internal_record->major_version != 2 )
388
61
  {
389
61
    libcerror_error_set(
390
61
     error,
391
61
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
392
61
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
393
61
     "%s: unsupported major version.",
394
61
     function );
395
396
61
    goto on_error;
397
61
  }
398
767
  if( ( (size_t) internal_record->size < sizeof( fusn_record_header_t ) )
399
767
   || ( (size_t) internal_record->size > byte_stream_size ) )
400
160
  {
401
160
    libcerror_error_set(
402
160
     error,
403
160
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
404
160
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
405
160
     "%s: record size value out of bounds.",
406
160
     function );
407
408
160
    goto on_error;
409
160
  }
410
607
  if( name_offset > 0 )
411
343
  {
412
343
    if( ( (size_t) name_offset < sizeof( fusn_record_header_t ) )
413
343
     || ( (size_t) name_offset > internal_record->size ) )
414
66
    {
415
66
      libcerror_error_set(
416
66
       error,
417
66
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
418
66
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
419
66
       "%s: name offset value out of bounds.",
420
66
       function );
421
422
66
      goto on_error;
423
66
    }
424
277
    if( (size_t) name_size > ( internal_record->size - name_offset ) )
425
49
    {
426
49
      libcerror_error_set(
427
49
       error,
428
49
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
429
49
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
430
49
       "%s: name size value out of bounds.",
431
49
       function );
432
433
49
      goto on_error;
434
49
    }
435
228
    if( (size_t) name_offset > byte_stream_offset )
436
88
    {
437
#if defined( HAVE_DEBUG_OUTPUT )
438
      if( libcnotify_verbose != 0 )
439
      {
440
        libcnotify_printf(
441
         "%s: record header trailing data:\n",
442
         function );
443
        libcnotify_print_data(
444
         &( byte_stream[ byte_stream_offset ] ),
445
         (size_t) name_offset - byte_stream_offset,
446
         0 );
447
      }
448
#endif
449
88
      byte_stream_offset = (size_t) name_offset;
450
88
    }
451
#if defined( HAVE_DEBUG_OUTPUT )
452
    if( libcnotify_verbose != 0 )
453
    {
454
      libcnotify_printf(
455
       "%s: name data:\n",
456
       function );
457
      libcnotify_print_data(
458
       &( byte_stream[ name_offset ] ),
459
       (size_t) name_size,
460
       0 );
461
    }
462
#endif
463
228
    internal_record->name = (uint8_t *) memory_allocate(
464
228
                                         sizeof( uint8_t ) * name_size );
465
466
228
    if( internal_record->name == NULL )
467
0
    {
468
0
      libcerror_error_set(
469
0
       error,
470
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
471
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
472
0
       "%s: unable to create name.",
473
0
       function );
474
475
0
      goto on_error;
476
0
    }
477
228
    internal_record->name_size = name_size;
478
479
228
    if( memory_copy(
480
228
         internal_record->name,
481
228
         &( byte_stream[ name_offset ] ),
482
228
         name_size ) == NULL )
483
0
    {
484
0
      libcerror_error_set(
485
0
       error,
486
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
487
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
488
0
       "%s: unable to copy name.",
489
0
       function );
490
491
0
      goto on_error;
492
0
    }
493
#if defined( HAVE_DEBUG_OUTPUT )
494
    if( libcnotify_verbose != 0 )
495
    {
496
      if( libfusn_debug_print_utf16_string_value(
497
           function,
498
           "name\t\t\t\t\t",
499
           internal_record->name,
500
           internal_record->name_size,
501
           LIBUNA_ENDIAN_LITTLE,
502
           error ) != 1 )
503
      {
504
        libcerror_error_set(
505
         error,
506
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
507
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
508
         "%s: unable to print UTF-16 string value.",
509
         function );
510
511
        return( -1 );
512
      }
513
    }
514
#endif
515
228
    byte_stream_offset += (size_t) name_size;
516
228
  }
517
#if defined( HAVE_DEBUG_OUTPUT )
518
  if( libcnotify_verbose != 0 )
519
  {
520
    if( byte_stream_offset < (size_t) internal_record->size )
521
    {
522
      libcnotify_printf(
523
       "%s: trailing data:\n",
524
       function );
525
      libcnotify_print_data(
526
       &( byte_stream[ byte_stream_offset ] ),
527
       (size_t) internal_record->size - byte_stream_offset,
528
       0 );
529
    }
530
    else
531
    {
532
      libcnotify_printf(
533
       "\n" );
534
    }
535
  }
536
#endif
537
492
  return( 1 );
538
539
336
on_error:
540
336
  if( internal_record->name != NULL )
541
0
  {
542
0
    memory_free(
543
0
     internal_record->name );
544
545
0
    internal_record->name = NULL;
546
0
  }
547
336
  internal_record->name_size = 0;
548
549
336
  return( -1 );
550
607
}
551
552
/* Retrieves the size
553
 * Returns 1 if successful or -1 on error
554
 */
555
int libfusn_record_get_size(
556
     libfusn_record_t *record,
557
     uint32_t *size,
558
     libcerror_error_t **error )
559
479
{
560
479
  libfusn_internal_record_t *internal_record = NULL;
561
479
  static char *function                      = "libfusn_record_get_size";
562
563
479
  if( record == NULL )
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
568
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
569
0
     "%s: invalid record.",
570
0
     function );
571
572
0
    return( -1 );
573
0
  }
574
479
  internal_record = (libfusn_internal_record_t *) record;
575
576
479
  if( size == NULL )
577
0
  {
578
0
    libcerror_error_set(
579
0
     error,
580
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
581
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
582
0
     "%s: invalid size.",
583
0
     function );
584
585
0
    return( -1 );
586
0
  }
587
479
  *size = internal_record->size;
588
589
479
  return( 1 );
590
479
}
591
592
/* Retrieves the update time
593
 * Returns 1 if successful or -1 on error
594
 */
595
int libfusn_record_get_update_time(
596
     libfusn_record_t *record,
597
     uint64_t *update_time,
598
     libcerror_error_t **error )
599
0
{
600
0
  libfusn_internal_record_t *internal_record = NULL;
601
0
  static char *function                      = "libfusn_record_get_update_time";
602
603
0
  if( record == NULL )
604
0
  {
605
0
    libcerror_error_set(
606
0
     error,
607
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
608
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
609
0
     "%s: invalid record.",
610
0
     function );
611
612
0
    return( -1 );
613
0
  }
614
0
  internal_record = (libfusn_internal_record_t *) record;
615
616
0
  if( update_time == NULL )
617
0
  {
618
0
    libcerror_error_set(
619
0
     error,
620
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
621
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
622
0
     "%s: invalid update time.",
623
0
     function );
624
625
0
    return( -1 );
626
0
  }
627
0
  *update_time = internal_record->update_time;
628
629
0
  return( 1 );
630
0
}
631
632
/* Retrieves the file reference
633
 * Returns 1 if successful or -1 on error
634
 */
635
int libfusn_record_get_file_reference(
636
     libfusn_record_t *record,
637
     uint64_t *file_reference,
638
     libcerror_error_t **error )
639
0
{
640
0
  libfusn_internal_record_t *internal_record = NULL;
641
0
  static char *function                      = "libfusn_record_get_file_reference";
642
643
0
  if( record == NULL )
644
0
  {
645
0
    libcerror_error_set(
646
0
     error,
647
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
648
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
649
0
     "%s: invalid record.",
650
0
     function );
651
652
0
    return( -1 );
653
0
  }
654
0
  internal_record = (libfusn_internal_record_t *) record;
655
656
0
  if( file_reference == NULL )
657
0
  {
658
0
    libcerror_error_set(
659
0
     error,
660
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
661
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
662
0
     "%s: invalid file reference.",
663
0
     function );
664
665
0
    return( -1 );
666
0
  }
667
0
  *file_reference = internal_record->file_reference;
668
669
0
  return( 1 );
670
0
}
671
672
/* Retrieves the parent file reference
673
 * Returns 1 if successful or -1 on error
674
 */
675
int libfusn_record_get_parent_file_reference(
676
     libfusn_record_t *record,
677
     uint64_t *parent_file_reference,
678
     libcerror_error_t **error )
679
0
{
680
0
  libfusn_internal_record_t *internal_record = NULL;
681
0
  static char *function                      = "libfusn_record_get_parent_file_reference";
682
683
0
  if( record == NULL )
684
0
  {
685
0
    libcerror_error_set(
686
0
     error,
687
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
688
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
689
0
     "%s: invalid record.",
690
0
     function );
691
692
0
    return( -1 );
693
0
  }
694
0
  internal_record = (libfusn_internal_record_t *) record;
695
696
0
  if( parent_file_reference == NULL )
697
0
  {
698
0
    libcerror_error_set(
699
0
     error,
700
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
701
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
702
0
     "%s: invalid parent file reference.",
703
0
     function );
704
705
0
    return( -1 );
706
0
  }
707
0
  *parent_file_reference = internal_record->parent_file_reference;
708
709
0
  return( 1 );
710
0
}
711
712
/* Retrieves the update sequence number
713
 * Returns 1 if successful or -1 on error
714
 */
715
int libfusn_record_get_update_sequence_number(
716
     libfusn_record_t *record,
717
     uint64_t *update_sequence_number,
718
     libcerror_error_t **error )
719
0
{
720
0
  libfusn_internal_record_t *internal_record = NULL;
721
0
  static char *function                      = "libfusn_record_get_update_sequence_number";
722
723
0
  if( record == NULL )
724
0
  {
725
0
    libcerror_error_set(
726
0
     error,
727
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
728
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
729
0
     "%s: invalid record.",
730
0
     function );
731
732
0
    return( -1 );
733
0
  }
734
0
  internal_record = (libfusn_internal_record_t *) record;
735
736
0
  if( update_sequence_number == NULL )
737
0
  {
738
0
    libcerror_error_set(
739
0
     error,
740
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
741
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
742
0
     "%s: invalid update sequence number.",
743
0
     function );
744
745
0
    return( -1 );
746
0
  }
747
0
  *update_sequence_number = internal_record->update_sequence_number;
748
749
0
  return( 1 );
750
0
}
751
752
/* Retrieves the update reason flags
753
 * Returns 1 if successful or -1 on error
754
 */
755
int libfusn_record_get_update_reason_flags(
756
     libfusn_record_t *record,
757
     uint32_t *update_reason_flags,
758
     libcerror_error_t **error )
759
0
{
760
0
  libfusn_internal_record_t *internal_record = NULL;
761
0
  static char *function                      = "libfusn_record_get_update_reason_flags";
762
763
0
  if( record == NULL )
764
0
  {
765
0
    libcerror_error_set(
766
0
     error,
767
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
768
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
769
0
     "%s: invalid record.",
770
0
     function );
771
772
0
    return( -1 );
773
0
  }
774
0
  internal_record = (libfusn_internal_record_t *) record;
775
776
0
  if( update_reason_flags == NULL )
777
0
  {
778
0
    libcerror_error_set(
779
0
     error,
780
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
781
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
782
0
     "%s: invalid update reason flags.",
783
0
     function );
784
785
0
    return( -1 );
786
0
  }
787
0
  *update_reason_flags = internal_record->update_reason_flags;
788
789
0
  return( 1 );
790
0
}
791
792
/* Retrieves the update source flags
793
 * Returns 1 if successful or -1 on error
794
 */
795
int libfusn_record_get_update_source_flags(
796
     libfusn_record_t *record,
797
     uint32_t *update_source_flags,
798
     libcerror_error_t **error )
799
0
{
800
0
  libfusn_internal_record_t *internal_record = NULL;
801
0
  static char *function                      = "libfusn_record_get_update_source_flags";
802
803
0
  if( record == NULL )
804
0
  {
805
0
    libcerror_error_set(
806
0
     error,
807
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
808
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
809
0
     "%s: invalid record.",
810
0
     function );
811
812
0
    return( -1 );
813
0
  }
814
0
  internal_record = (libfusn_internal_record_t *) record;
815
816
0
  if( update_source_flags == NULL )
817
0
  {
818
0
    libcerror_error_set(
819
0
     error,
820
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
821
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
822
0
     "%s: invalid update source flags.",
823
0
     function );
824
825
0
    return( -1 );
826
0
  }
827
0
  *update_source_flags = internal_record->update_source_flags;
828
829
0
  return( 1 );
830
0
}
831
832
/* Retrieves the file attribute flags
833
 * Returns 1 if successful or -1 on error
834
 */
835
int libfusn_record_get_file_attribute_flags(
836
     libfusn_record_t *record,
837
     uint32_t *file_attribute_flags,
838
     libcerror_error_t **error )
839
0
{
840
0
  libfusn_internal_record_t *internal_record = NULL;
841
0
  static char *function                      = "libfusn_record_get_file_attribute_flags";
842
843
0
  if( record == NULL )
844
0
  {
845
0
    libcerror_error_set(
846
0
     error,
847
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
848
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
849
0
     "%s: invalid record.",
850
0
     function );
851
852
0
    return( -1 );
853
0
  }
854
0
  internal_record = (libfusn_internal_record_t *) record;
855
856
0
  if( file_attribute_flags == NULL )
857
0
  {
858
0
    libcerror_error_set(
859
0
     error,
860
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
861
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
862
0
     "%s: invalid file attribute flags.",
863
0
     function );
864
865
0
    return( -1 );
866
0
  }
867
0
  *file_attribute_flags = internal_record->file_attribute_flags;
868
869
0
  return( 1 );
870
0
}
871
872
/* Retrieves the size of the UTF-8 encoded name
873
 * The returned size includes the end of string character
874
 * Returns 1 if successful or -1 on error
875
 */
876
int libfusn_record_get_utf8_name_size(
877
     libfusn_record_t *record,
878
     size_t *utf8_string_size,
879
     libcerror_error_t **error )
880
0
{
881
0
  libfusn_internal_record_t *internal_record = NULL;
882
0
  static char *function                      = "libfusn_record_get_utf8_name_size";
883
884
0
  if( record == NULL )
885
0
  {
886
0
    libcerror_error_set(
887
0
     error,
888
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
889
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
890
0
     "%s: invalid record.",
891
0
     function );
892
893
0
    return( -1 );
894
0
  }
895
0
  internal_record = (libfusn_internal_record_t *) record;
896
897
0
  if( ( internal_record->name == NULL )
898
0
   || ( internal_record->name_size == 0 ) )
899
0
  {
900
0
    if( utf8_string_size == NULL )
901
0
    {
902
0
      libcerror_error_set(
903
0
       error,
904
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
905
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
906
0
       "%s: invalid UTF-8 string size.",
907
0
       function );
908
909
0
      return( -1 );
910
0
    }
911
0
    *utf8_string_size = 0;
912
0
  }
913
0
  else
914
0
  {
915
0
    if( libuna_utf8_string_size_from_utf16_stream(
916
0
         internal_record->name,
917
0
         (size_t) internal_record->name_size,
918
0
         LIBUNA_ENDIAN_LITTLE,
919
0
         utf8_string_size,
920
0
         error ) != 1 )
921
0
    {
922
0
      libcerror_error_set(
923
0
       error,
924
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
925
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
926
0
       "%s: unable to retrieve UTF-8 string size.",
927
0
       function );
928
929
0
      return( -1 );
930
0
    }
931
0
  }
932
0
  return( 1 );
933
0
}
934
935
/* Retrieves the UTF-8 encoded name
936
 * The size should include the end of string character
937
 * Returns 1 if successful or -1 on error
938
 */
939
int libfusn_record_get_utf8_name(
940
     libfusn_record_t *record,
941
     uint8_t *utf8_string,
942
     size_t utf8_string_size,
943
     libcerror_error_t **error )
944
0
{
945
0
  libfusn_internal_record_t *internal_record = NULL;
946
0
  static char *function                      = "libfusn_record_get_utf8_name";
947
948
0
  if( record == NULL )
949
0
  {
950
0
    libcerror_error_set(
951
0
     error,
952
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
953
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
954
0
     "%s: invalid record.",
955
0
     function );
956
957
0
    return( -1 );
958
0
  }
959
0
  internal_record = (libfusn_internal_record_t *) record;
960
961
0
  if( internal_record->name == NULL )
962
0
  {
963
0
    libcerror_error_set(
964
0
     error,
965
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
966
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
967
0
     "%s: invalid record - missing name.",
968
0
     function );
969
970
0
    return( -1 );
971
0
  }
972
0
  if( libuna_utf8_string_copy_from_utf16_stream(
973
0
       utf8_string,
974
0
       utf8_string_size,
975
0
       internal_record->name,
976
0
       (size_t) internal_record->name_size,
977
0
       LIBUNA_ENDIAN_LITTLE,
978
0
       error ) != 1 )
979
0
  {
980
0
    libcerror_error_set(
981
0
     error,
982
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
983
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
984
0
     "%s: unable to retrieve UTF-8 string.",
985
0
     function );
986
987
0
    return( -1 );
988
0
  }
989
0
  return( 1 );
990
0
}
991
992
/* Retrieves the size of the UTF-16 encoded name
993
 * The returned size includes the end of string character
994
 * Returns 1 if successful or -1 on error
995
 */
996
int libfusn_record_get_utf16_name_size(
997
     libfusn_record_t *record,
998
     size_t *utf16_string_size,
999
     libcerror_error_t **error )
1000
0
{
1001
0
  libfusn_internal_record_t *internal_record = NULL;
1002
0
  static char *function                      = "libfusn_record_get_utf16_name_size";
1003
1004
0
  if( record == NULL )
1005
0
  {
1006
0
    libcerror_error_set(
1007
0
     error,
1008
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1009
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1010
0
     "%s: invalid record.",
1011
0
     function );
1012
1013
0
    return( -1 );
1014
0
  }
1015
0
  internal_record = (libfusn_internal_record_t *) record;
1016
1017
0
  if( ( internal_record->name == NULL )
1018
0
   || ( internal_record->name_size == 0 ) )
1019
0
  {
1020
0
    if( utf16_string_size == NULL )
1021
0
    {
1022
0
      libcerror_error_set(
1023
0
       error,
1024
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1025
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1026
0
       "%s: invalid UTF-16 string size.",
1027
0
       function );
1028
1029
0
      return( -1 );
1030
0
    }
1031
0
    *utf16_string_size = 0;
1032
0
  }
1033
0
  else
1034
0
  {
1035
0
    if( libuna_utf16_string_size_from_utf16_stream(
1036
0
         internal_record->name,
1037
0
         (size_t) internal_record->name_size,
1038
0
         LIBUNA_ENDIAN_LITTLE,
1039
0
         utf16_string_size,
1040
0
         error ) != 1 )
1041
0
    {
1042
0
      libcerror_error_set(
1043
0
       error,
1044
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1045
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1046
0
       "%s: unable to retrieve UTF-16 string size.",
1047
0
       function );
1048
1049
0
      return( -1 );
1050
0
    }
1051
0
  }
1052
0
  return( 1 );
1053
0
}
1054
1055
/* Retrieves the UTF-16 encoded name
1056
 * The size should include the end of string character
1057
 * Returns 1 if successful or -1 on error
1058
 */
1059
int libfusn_record_get_utf16_name(
1060
     libfusn_record_t *record,
1061
     uint16_t *utf16_string,
1062
     size_t utf16_string_size,
1063
     libcerror_error_t **error )
1064
0
{
1065
0
  libfusn_internal_record_t *internal_record = NULL;
1066
0
  static char *function                      = "libfusn_record_get_utf16_name";
1067
1068
0
  if( record == NULL )
1069
0
  {
1070
0
    libcerror_error_set(
1071
0
     error,
1072
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1073
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1074
0
     "%s: invalid record.",
1075
0
     function );
1076
1077
0
    return( -1 );
1078
0
  }
1079
0
  internal_record = (libfusn_internal_record_t *) record;
1080
1081
0
  if( internal_record->name == NULL )
1082
0
  {
1083
0
    libcerror_error_set(
1084
0
     error,
1085
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1086
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1087
0
     "%s: invalid record - missing name.",
1088
0
     function );
1089
1090
0
    return( -1 );
1091
0
  }
1092
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1093
0
       utf16_string,
1094
0
       utf16_string_size,
1095
0
       internal_record->name,
1096
0
       (size_t) internal_record->name_size,
1097
0
       LIBUNA_ENDIAN_LITTLE,
1098
0
       error ) != 1 )
1099
0
  {
1100
0
    libcerror_error_set(
1101
0
     error,
1102
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1103
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1104
0
     "%s: unable to retrieve UTF-16 string.",
1105
0
     function );
1106
1107
0
    return( -1 );
1108
0
  }
1109
0
  return( 1 );
1110
0
}
1111