Coverage Report

Created: 2026-07-25 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfusn/libfusn/libfusn_record.c
Line
Count
Source
1
/*
2
 * Record functions
3
 *
4
 * Copyright (C) 2011-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 <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
926
{
47
926
  libfusn_internal_record_t *internal_record = NULL;
48
926
  static char *function                      = "libfusn_record_initialize";
49
50
926
  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
926
  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
926
  internal_record = memory_allocate_structure(
73
926
         libfusn_internal_record_t );
74
75
926
  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
926
  if( memory_set(
87
926
       internal_record,
88
926
       0,
89
926
       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
926
  *record = (libfusn_record_t *) internal_record;
101
102
926
  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
926
}
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
926
{
120
926
  libfusn_internal_record_t *internal_record = NULL;
121
926
  static char *function                      = "libfusn_record_free";
122
123
926
  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
926
  if( *record != NULL )
135
926
  {
136
926
    internal_record = (libfusn_internal_record_t *) *record;
137
926
    *record         = NULL;
138
139
926
    if( internal_record->name != NULL )
140
263
    {
141
263
      memory_free(
142
263
       internal_record->name );
143
263
    }
144
926
    memory_free(
145
926
     internal_record );
146
926
  }
147
926
  return( 1 );
148
926
}
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
926
{
159
926
  libfusn_internal_record_t *internal_record = NULL;
160
926
  static char *function                      = "libfusn_record_copy_from_byte_stream";
161
926
  size_t byte_stream_offset                  = 0;
162
926
  uint16_t name_offset                       = 0;
163
926
  uint16_t name_size                         = 0;
164
165
#if defined( HAVE_DEBUG_OUTPUT )
166
  uint32_t value_32bit                       = 0;
167
#endif
168
169
926
  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
926
  internal_record = (libfusn_internal_record_t *) record;
181
182
926
  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
926
  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
926
  if( byte_stream_size > (size_t) SSIZE_MAX )
205
32
  {
206
32
    libcerror_error_set(
207
32
     error,
208
32
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
209
32
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
210
32
     "%s: invalid byte stream size value exceeds maximum.",
211
32
     function );
212
213
32
    return( -1 );
214
32
  }
215
894
  if( byte_stream_size < sizeof( fusn_record_header_t ) )
216
36
  {
217
36
    libcerror_error_set(
218
36
     error,
219
36
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
220
36
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
221
36
     "%s: invalid byte stream value too small.",
222
36
     function );
223
224
36
    return( -1 );
225
36
  }
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
858
  byte_stream_copy_to_uint32_little_endian(
239
858
   ( (fusn_record_header_t *) byte_stream )->record_size,
240
858
   internal_record->size );
241
242
858
  byte_stream_copy_to_uint16_little_endian(
243
858
   ( (fusn_record_header_t *) byte_stream )->major_version,
244
858
   internal_record->major_version );
245
246
858
  byte_stream_copy_to_uint16_little_endian(
247
858
   ( (fusn_record_header_t *) byte_stream )->minor_version,
248
858
   internal_record->minor_version );
249
250
858
  byte_stream_copy_to_uint64_little_endian(
251
858
   ( (fusn_record_header_t *) byte_stream )->update_time,
252
858
   internal_record->update_time );
253
254
858
  byte_stream_copy_to_uint64_little_endian(
255
858
   ( (fusn_record_header_t *) byte_stream )->file_reference,
256
858
   internal_record->file_reference );
257
258
858
  byte_stream_copy_to_uint32_little_endian(
259
858
   ( (fusn_record_header_t *) byte_stream )->file_attribute_flags,
260
858
   internal_record->file_attribute_flags );
261
262
858
  byte_stream_copy_to_uint64_little_endian(
263
858
   ( (fusn_record_header_t *) byte_stream )->parent_file_reference,
264
858
   internal_record->parent_file_reference );
265
266
858
  byte_stream_copy_to_uint64_little_endian(
267
858
   ( (fusn_record_header_t *) byte_stream )->update_sequence_number,
268
858
   internal_record->update_sequence_number );
269
270
858
  byte_stream_copy_to_uint32_little_endian(
271
858
   ( (fusn_record_header_t *) byte_stream )->update_reason_flags,
272
858
   internal_record->update_reason_flags );
273
274
858
  byte_stream_copy_to_uint32_little_endian(
275
858
   ( (fusn_record_header_t *) byte_stream )->update_source_flags,
276
858
   internal_record->update_source_flags );
277
278
858
  byte_stream_copy_to_uint16_little_endian(
279
858
   ( (fusn_record_header_t *) byte_stream )->name_size,
280
858
   name_size );
281
282
858
  byte_stream_copy_to_uint16_little_endian(
283
858
   ( (fusn_record_header_t *) byte_stream )->name_offset,
284
858
   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 /* defined( HAVE_DEBUG_OUTPUT ) */
385
386
858
  byte_stream_offset = sizeof( fusn_record_header_t );
387
388
858
  if( internal_record->major_version != 2 )
389
74
  {
390
74
    libcerror_error_set(
391
74
     error,
392
74
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
393
74
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
394
74
     "%s: unsupported major version.",
395
74
     function );
396
397
74
    goto on_error;
398
74
  }
399
784
  if( ( (size_t) internal_record->size < sizeof( fusn_record_header_t ) )
400
774
   || ( (size_t) internal_record->size > byte_stream_size ) )
401
99
  {
402
99
    libcerror_error_set(
403
99
     error,
404
99
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
405
99
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
406
99
     "%s: record size value out of bounds.",
407
99
     function );
408
409
99
    goto on_error;
410
99
  }
411
685
  if( name_offset > 0 )
412
400
  {
413
400
    if( ( (size_t) name_offset < sizeof( fusn_record_header_t ) )
414
385
     || ( (size_t) name_offset > internal_record->size ) )
415
88
    {
416
88
      libcerror_error_set(
417
88
       error,
418
88
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
419
88
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
420
88
       "%s: name offset value out of bounds.",
421
88
       function );
422
423
88
      goto on_error;
424
88
    }
425
312
    if( (size_t) name_size > ( internal_record->size - name_offset ) )
426
49
    {
427
49
      libcerror_error_set(
428
49
       error,
429
49
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
430
49
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
431
49
       "%s: name size value out of bounds.",
432
49
       function );
433
434
49
      goto on_error;
435
49
    }
436
263
    if( (size_t) name_offset > byte_stream_offset )
437
43
    {
438
#if defined( HAVE_DEBUG_OUTPUT )
439
      if( libcnotify_verbose != 0 )
440
      {
441
        libcnotify_printf(
442
         "%s: record header trailing data:\n",
443
         function );
444
        libcnotify_print_data(
445
         &( byte_stream[ byte_stream_offset ] ),
446
         (size_t) name_offset - byte_stream_offset,
447
         0 );
448
449
        byte_stream_offset = (size_t) name_offset;
450
      }
451
#endif
452
43
    }
453
#if defined( HAVE_DEBUG_OUTPUT )
454
    if( libcnotify_verbose != 0 )
455
    {
456
      libcnotify_printf(
457
       "%s: name data:\n",
458
       function );
459
      libcnotify_print_data(
460
       &( byte_stream[ name_offset ] ),
461
       (size_t) name_size,
462
       0 );
463
    }
464
#endif
465
263
    internal_record->name = (uint8_t *) memory_allocate(
466
263
                                         sizeof( uint8_t ) * name_size );
467
468
263
    if( internal_record->name == NULL )
469
0
    {
470
0
      libcerror_error_set(
471
0
       error,
472
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
473
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
474
0
       "%s: unable to create name.",
475
0
       function );
476
477
0
      goto on_error;
478
0
    }
479
263
    internal_record->name_size = name_size;
480
481
263
    if( memory_copy(
482
263
         internal_record->name,
483
263
         &( byte_stream[ name_offset ] ),
484
263
         name_size ) == NULL )
485
0
    {
486
0
      libcerror_error_set(
487
0
       error,
488
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
489
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
490
0
       "%s: unable to copy name.",
491
0
       function );
492
493
0
      goto on_error;
494
0
    }
495
#if defined( HAVE_DEBUG_OUTPUT )
496
    if( libcnotify_verbose != 0 )
497
    {
498
      if( libfusn_debug_print_utf16_string_value(
499
           function,
500
           "name\t\t\t\t\t",
501
           internal_record->name,
502
           internal_record->name_size,
503
           LIBUNA_ENDIAN_LITTLE,
504
           error ) != 1 )
505
      {
506
        libcerror_error_set(
507
         error,
508
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
509
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
510
         "%s: unable to print UTF-16 string value.",
511
         function );
512
513
        return( -1 );
514
      }
515
      byte_stream_offset += (size_t) name_size;
516
    }
517
#endif
518
263
  }
519
#if defined( HAVE_DEBUG_OUTPUT )
520
  if( libcnotify_verbose != 0 )
521
  {
522
    if( byte_stream_offset < (size_t) internal_record->size )
523
    {
524
      libcnotify_printf(
525
       "%s: trailing data:\n",
526
       function );
527
      libcnotify_print_data(
528
       &( byte_stream[ byte_stream_offset ] ),
529
       (size_t) internal_record->size - byte_stream_offset,
530
       0 );
531
    }
532
    else
533
    {
534
      libcnotify_printf(
535
       "\n" );
536
    }
537
  }
538
#endif
539
548
  return( 1 );
540
541
310
on_error:
542
310
  if( internal_record->name != NULL )
543
0
  {
544
0
    memory_free(
545
0
     internal_record->name );
546
547
0
    internal_record->name = NULL;
548
0
  }
549
310
  internal_record->name_size = 0;
550
551
310
  return( -1 );
552
685
}
553
554
/* Retrieves the size
555
 * Returns 1 if successful or -1 on error
556
 */
557
int libfusn_record_get_size(
558
     libfusn_record_t *record,
559
     uint32_t *size,
560
     libcerror_error_t **error )
561
521
{
562
521
  libfusn_internal_record_t *internal_record = NULL;
563
521
  static char *function                      = "libfusn_record_get_size";
564
565
521
  if( record == NULL )
566
0
  {
567
0
    libcerror_error_set(
568
0
     error,
569
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
570
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
571
0
     "%s: invalid record.",
572
0
     function );
573
574
0
    return( -1 );
575
0
  }
576
521
  internal_record = (libfusn_internal_record_t *) record;
577
578
521
  if( size == NULL )
579
0
  {
580
0
    libcerror_error_set(
581
0
     error,
582
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
583
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
584
0
     "%s: invalid size.",
585
0
     function );
586
587
0
    return( -1 );
588
0
  }
589
521
  *size = internal_record->size;
590
591
521
  return( 1 );
592
521
}
593
594
/* Retrieves the update time
595
 * Returns 1 if successful or -1 on error
596
 */
597
int libfusn_record_get_update_time(
598
     libfusn_record_t *record,
599
     uint64_t *update_time,
600
     libcerror_error_t **error )
601
0
{
602
0
  libfusn_internal_record_t *internal_record = NULL;
603
0
  static char *function                      = "libfusn_record_get_update_time";
604
605
0
  if( record == NULL )
606
0
  {
607
0
    libcerror_error_set(
608
0
     error,
609
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
610
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
611
0
     "%s: invalid record.",
612
0
     function );
613
614
0
    return( -1 );
615
0
  }
616
0
  internal_record = (libfusn_internal_record_t *) record;
617
618
0
  if( update_time == NULL )
619
0
  {
620
0
    libcerror_error_set(
621
0
     error,
622
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
623
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
624
0
     "%s: invalid update time.",
625
0
     function );
626
627
0
    return( -1 );
628
0
  }
629
0
  *update_time = internal_record->update_time;
630
631
0
  return( 1 );
632
0
}
633
634
/* Retrieves the file reference
635
 * Returns 1 if successful or -1 on error
636
 */
637
int libfusn_record_get_file_reference(
638
     libfusn_record_t *record,
639
     uint64_t *file_reference,
640
     libcerror_error_t **error )
641
0
{
642
0
  libfusn_internal_record_t *internal_record = NULL;
643
0
  static char *function                      = "libfusn_record_get_file_reference";
644
645
0
  if( record == NULL )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
650
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
651
0
     "%s: invalid record.",
652
0
     function );
653
654
0
    return( -1 );
655
0
  }
656
0
  internal_record = (libfusn_internal_record_t *) record;
657
658
0
  if( file_reference == NULL )
659
0
  {
660
0
    libcerror_error_set(
661
0
     error,
662
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
663
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
664
0
     "%s: invalid file reference.",
665
0
     function );
666
667
0
    return( -1 );
668
0
  }
669
0
  *file_reference = internal_record->file_reference;
670
671
0
  return( 1 );
672
0
}
673
674
/* Retrieves the parent file reference
675
 * Returns 1 if successful or -1 on error
676
 */
677
int libfusn_record_get_parent_file_reference(
678
     libfusn_record_t *record,
679
     uint64_t *parent_file_reference,
680
     libcerror_error_t **error )
681
0
{
682
0
  libfusn_internal_record_t *internal_record = NULL;
683
0
  static char *function                      = "libfusn_record_get_parent_file_reference";
684
685
0
  if( record == NULL )
686
0
  {
687
0
    libcerror_error_set(
688
0
     error,
689
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
690
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
691
0
     "%s: invalid record.",
692
0
     function );
693
694
0
    return( -1 );
695
0
  }
696
0
  internal_record = (libfusn_internal_record_t *) record;
697
698
0
  if( parent_file_reference == NULL )
699
0
  {
700
0
    libcerror_error_set(
701
0
     error,
702
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
703
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
704
0
     "%s: invalid parent file reference.",
705
0
     function );
706
707
0
    return( -1 );
708
0
  }
709
0
  *parent_file_reference = internal_record->parent_file_reference;
710
711
0
  return( 1 );
712
0
}
713
714
/* Retrieves the update sequence number
715
 * Returns 1 if successful or -1 on error
716
 */
717
int libfusn_record_get_update_sequence_number(
718
     libfusn_record_t *record,
719
     uint64_t *update_sequence_number,
720
     libcerror_error_t **error )
721
0
{
722
0
  libfusn_internal_record_t *internal_record = NULL;
723
0
  static char *function                      = "libfusn_record_get_update_sequence_number";
724
725
0
  if( record == NULL )
726
0
  {
727
0
    libcerror_error_set(
728
0
     error,
729
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
730
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
731
0
     "%s: invalid record.",
732
0
     function );
733
734
0
    return( -1 );
735
0
  }
736
0
  internal_record = (libfusn_internal_record_t *) record;
737
738
0
  if( update_sequence_number == NULL )
739
0
  {
740
0
    libcerror_error_set(
741
0
     error,
742
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
743
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
744
0
     "%s: invalid update sequence number.",
745
0
     function );
746
747
0
    return( -1 );
748
0
  }
749
0
  *update_sequence_number = internal_record->update_sequence_number;
750
751
0
  return( 1 );
752
0
}
753
754
/* Retrieves the update reason flags
755
 * Returns 1 if successful or -1 on error
756
 */
757
int libfusn_record_get_update_reason_flags(
758
     libfusn_record_t *record,
759
     uint32_t *update_reason_flags,
760
     libcerror_error_t **error )
761
0
{
762
0
  libfusn_internal_record_t *internal_record = NULL;
763
0
  static char *function                      = "libfusn_record_get_update_reason_flags";
764
765
0
  if( record == NULL )
766
0
  {
767
0
    libcerror_error_set(
768
0
     error,
769
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
770
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
771
0
     "%s: invalid record.",
772
0
     function );
773
774
0
    return( -1 );
775
0
  }
776
0
  internal_record = (libfusn_internal_record_t *) record;
777
778
0
  if( update_reason_flags == NULL )
779
0
  {
780
0
    libcerror_error_set(
781
0
     error,
782
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
783
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
784
0
     "%s: invalid update reason flags.",
785
0
     function );
786
787
0
    return( -1 );
788
0
  }
789
0
  *update_reason_flags = internal_record->update_reason_flags;
790
791
0
  return( 1 );
792
0
}
793
794
/* Retrieves the update source flags
795
 * Returns 1 if successful or -1 on error
796
 */
797
int libfusn_record_get_update_source_flags(
798
     libfusn_record_t *record,
799
     uint32_t *update_source_flags,
800
     libcerror_error_t **error )
801
0
{
802
0
  libfusn_internal_record_t *internal_record = NULL;
803
0
  static char *function                      = "libfusn_record_get_update_source_flags";
804
805
0
  if( record == NULL )
806
0
  {
807
0
    libcerror_error_set(
808
0
     error,
809
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
810
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
811
0
     "%s: invalid record.",
812
0
     function );
813
814
0
    return( -1 );
815
0
  }
816
0
  internal_record = (libfusn_internal_record_t *) record;
817
818
0
  if( update_source_flags == NULL )
819
0
  {
820
0
    libcerror_error_set(
821
0
     error,
822
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
823
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
824
0
     "%s: invalid update source flags.",
825
0
     function );
826
827
0
    return( -1 );
828
0
  }
829
0
  *update_source_flags = internal_record->update_source_flags;
830
831
0
  return( 1 );
832
0
}
833
834
/* Retrieves the file attribute flags
835
 * Returns 1 if successful or -1 on error
836
 */
837
int libfusn_record_get_file_attribute_flags(
838
     libfusn_record_t *record,
839
     uint32_t *file_attribute_flags,
840
     libcerror_error_t **error )
841
0
{
842
0
  libfusn_internal_record_t *internal_record = NULL;
843
0
  static char *function                      = "libfusn_record_get_file_attribute_flags";
844
845
0
  if( record == NULL )
846
0
  {
847
0
    libcerror_error_set(
848
0
     error,
849
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
850
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
851
0
     "%s: invalid record.",
852
0
     function );
853
854
0
    return( -1 );
855
0
  }
856
0
  internal_record = (libfusn_internal_record_t *) record;
857
858
0
  if( file_attribute_flags == NULL )
859
0
  {
860
0
    libcerror_error_set(
861
0
     error,
862
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
863
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
864
0
     "%s: invalid file attribute flags.",
865
0
     function );
866
867
0
    return( -1 );
868
0
  }
869
0
  *file_attribute_flags = internal_record->file_attribute_flags;
870
871
0
  return( 1 );
872
0
}
873
874
/* Retrieves the size of the UTF-8 encoded name
875
 * The returned size includes the end of string character
876
 * Returns 1 if successful or -1 on error
877
 */
878
int libfusn_record_get_utf8_name_size(
879
     libfusn_record_t *record,
880
     size_t *utf8_string_size,
881
     libcerror_error_t **error )
882
0
{
883
0
  libfusn_internal_record_t *internal_record = NULL;
884
0
  static char *function                      = "libfusn_record_get_utf8_name_size";
885
886
0
  if( record == NULL )
887
0
  {
888
0
    libcerror_error_set(
889
0
     error,
890
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
891
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
892
0
     "%s: invalid record.",
893
0
     function );
894
895
0
    return( -1 );
896
0
  }
897
0
  internal_record = (libfusn_internal_record_t *) record;
898
899
0
  if( ( internal_record->name == NULL )
900
0
   || ( internal_record->name_size == 0 ) )
901
0
  {
902
0
    if( utf8_string_size == NULL )
903
0
    {
904
0
      libcerror_error_set(
905
0
       error,
906
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
907
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
908
0
       "%s: invalid UTF-8 string size.",
909
0
       function );
910
911
0
      return( -1 );
912
0
    }
913
0
    *utf8_string_size = 0;
914
0
  }
915
0
  else
916
0
  {
917
0
    if( libuna_utf8_string_size_from_utf16_stream(
918
0
         internal_record->name,
919
0
         (size_t) internal_record->name_size,
920
0
         LIBUNA_ENDIAN_LITTLE,
921
0
         utf8_string_size,
922
0
         error ) != 1 )
923
0
    {
924
0
      libcerror_error_set(
925
0
       error,
926
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
927
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
928
0
       "%s: unable to retrieve UTF-8 string size.",
929
0
       function );
930
931
0
      return( -1 );
932
0
    }
933
0
  }
934
0
  return( 1 );
935
0
}
936
937
/* Retrieves the UTF-8 encoded name
938
 * The size should include the end of string character
939
 * Returns 1 if successful or -1 on error
940
 */
941
int libfusn_record_get_utf8_name(
942
     libfusn_record_t *record,
943
     uint8_t *utf8_string,
944
     size_t utf8_string_size,
945
     libcerror_error_t **error )
946
0
{
947
0
  libfusn_internal_record_t *internal_record = NULL;
948
0
  static char *function                      = "libfusn_record_get_utf8_name";
949
950
0
  if( record == NULL )
951
0
  {
952
0
    libcerror_error_set(
953
0
     error,
954
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
955
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
956
0
     "%s: invalid record.",
957
0
     function );
958
959
0
    return( -1 );
960
0
  }
961
0
  internal_record = (libfusn_internal_record_t *) record;
962
963
0
  if( internal_record->name == NULL )
964
0
  {
965
0
    libcerror_error_set(
966
0
     error,
967
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
968
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
969
0
     "%s: invalid record - missing name.",
970
0
     function );
971
972
0
    return( -1 );
973
0
  }
974
0
  if( libuna_utf8_string_copy_from_utf16_stream(
975
0
       utf8_string,
976
0
       utf8_string_size,
977
0
       internal_record->name,
978
0
       (size_t) internal_record->name_size,
979
0
       LIBUNA_ENDIAN_LITTLE,
980
0
       error ) != 1 )
981
0
  {
982
0
    libcerror_error_set(
983
0
     error,
984
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
985
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
986
0
     "%s: unable to retrieve UTF-8 string.",
987
0
     function );
988
989
0
    return( -1 );
990
0
  }
991
0
  return( 1 );
992
0
}
993
994
/* Retrieves the size of the UTF-16 encoded name
995
 * The returned size includes the end of string character
996
 * Returns 1 if successful or -1 on error
997
 */
998
int libfusn_record_get_utf16_name_size(
999
     libfusn_record_t *record,
1000
     size_t *utf16_string_size,
1001
     libcerror_error_t **error )
1002
0
{
1003
0
  libfusn_internal_record_t *internal_record = NULL;
1004
0
  static char *function                      = "libfusn_record_get_utf16_name_size";
1005
1006
0
  if( record == NULL )
1007
0
  {
1008
0
    libcerror_error_set(
1009
0
     error,
1010
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1011
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1012
0
     "%s: invalid record.",
1013
0
     function );
1014
1015
0
    return( -1 );
1016
0
  }
1017
0
  internal_record = (libfusn_internal_record_t *) record;
1018
1019
0
  if( ( internal_record->name == NULL )
1020
0
   || ( internal_record->name_size == 0 ) )
1021
0
  {
1022
0
    if( utf16_string_size == NULL )
1023
0
    {
1024
0
      libcerror_error_set(
1025
0
       error,
1026
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1027
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1028
0
       "%s: invalid UTF-16 string size.",
1029
0
       function );
1030
1031
0
      return( -1 );
1032
0
    }
1033
0
    *utf16_string_size = 0;
1034
0
  }
1035
0
  else
1036
0
  {
1037
0
    if( libuna_utf16_string_size_from_utf16_stream(
1038
0
         internal_record->name,
1039
0
         (size_t) internal_record->name_size,
1040
0
         LIBUNA_ENDIAN_LITTLE,
1041
0
         utf16_string_size,
1042
0
         error ) != 1 )
1043
0
    {
1044
0
      libcerror_error_set(
1045
0
       error,
1046
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1047
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1048
0
       "%s: unable to retrieve UTF-16 string size.",
1049
0
       function );
1050
1051
0
      return( -1 );
1052
0
    }
1053
0
  }
1054
0
  return( 1 );
1055
0
}
1056
1057
/* Retrieves the UTF-16 encoded name
1058
 * The size should include the end of string character
1059
 * Returns 1 if successful or -1 on error
1060
 */
1061
int libfusn_record_get_utf16_name(
1062
     libfusn_record_t *record,
1063
     uint16_t *utf16_string,
1064
     size_t utf16_string_size,
1065
     libcerror_error_t **error )
1066
0
{
1067
0
  libfusn_internal_record_t *internal_record = NULL;
1068
0
  static char *function                      = "libfusn_record_get_utf16_name";
1069
1070
0
  if( record == NULL )
1071
0
  {
1072
0
    libcerror_error_set(
1073
0
     error,
1074
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1075
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1076
0
     "%s: invalid record.",
1077
0
     function );
1078
1079
0
    return( -1 );
1080
0
  }
1081
0
  internal_record = (libfusn_internal_record_t *) record;
1082
1083
0
  if( internal_record->name == NULL )
1084
0
  {
1085
0
    libcerror_error_set(
1086
0
     error,
1087
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1088
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1089
0
     "%s: invalid record - missing name.",
1090
0
     function );
1091
1092
0
    return( -1 );
1093
0
  }
1094
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1095
0
       utf16_string,
1096
0
       utf16_string_size,
1097
0
       internal_record->name,
1098
0
       (size_t) internal_record->name_size,
1099
0
       LIBUNA_ENDIAN_LITTLE,
1100
0
       error ) != 1 )
1101
0
  {
1102
0
    libcerror_error_set(
1103
0
     error,
1104
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1105
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1106
0
     "%s: unable to retrieve UTF-16 string.",
1107
0
     function );
1108
1109
0
    return( -1 );
1110
0
  }
1111
0
  return( 1 );
1112
0
}
1113