Coverage Report

Created: 2024-02-25 07:20

/src/libftxf/libftxf/libftxf_record.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Record functions
3
 *
4
 * Copyright (C) 2010-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 "libftxf_debug.h"
31
#include "libftxf_definitions.h"
32
#include "libftxf_libcerror.h"
33
#include "libftxf_libcnotify.h"
34
#include "libftxf_libfdatetime.h"
35
#include "libftxf_libfguid.h"
36
#include "libftxf_libfusn.h"
37
#include "libftxf_libuna.h"
38
#include "libftxf_record.h"
39
40
#include "ftxf_record.h"
41
42
/* Creates a record
43
 * Make sure the value record is referencing, is set to NULL
44
 * Returns 1 if successful or -1 on error
45
 */
46
int libftxf_record_initialize(
47
     libftxf_record_t **record,
48
     libcerror_error_t **error )
49
488
{
50
488
  libftxf_internal_record_t *internal_record = NULL;
51
488
  static char *function                      = "libftxf_record_initialize";
52
53
488
  if( record == NULL )
54
0
  {
55
0
    libcerror_error_set(
56
0
     error,
57
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
58
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
59
0
     "%s: invalid record.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
488
  if( *record != NULL )
65
0
  {
66
0
    libcerror_error_set(
67
0
     error,
68
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
69
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
70
0
     "%s: invalid record value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
488
  internal_record = memory_allocate_structure(
76
488
                     libftxf_internal_record_t );
77
78
488
  if( internal_record == NULL )
79
0
  {
80
0
    libcerror_error_set(
81
0
     error,
82
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
83
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
84
0
     "%s: unable to create record.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
488
  if( memory_set(
90
488
       internal_record,
91
488
       0,
92
488
       sizeof( libftxf_internal_record_t ) ) == NULL )
93
0
  {
94
0
    libcerror_error_set(
95
0
     error,
96
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
97
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
98
0
     "%s: unable to clear record.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
488
  *record = (libftxf_record_t *) internal_record;
104
105
488
  return( 1 );
106
107
0
on_error:
108
0
  if( internal_record != NULL )
109
0
  {
110
0
    memory_free(
111
0
     internal_record );
112
0
  }
113
0
  return( -1 );
114
488
}
115
116
/* Frees a record
117
 * Returns 1 if successful or -1 on error
118
 */
119
int libftxf_record_free(
120
     libftxf_record_t **record,
121
     libcerror_error_t **error )
122
488
{
123
488
  libftxf_internal_record_t *internal_record = NULL;
124
488
  static char *function                      = "libftxf_record_free";
125
126
488
  if( record == NULL )
127
0
  {
128
0
    libcerror_error_set(
129
0
     error,
130
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
131
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
132
0
     "%s: invalid record.",
133
0
     function );
134
135
0
    return( -1 );
136
0
  }
137
488
  if( *record != NULL )
138
488
  {
139
488
    internal_record = (libftxf_internal_record_t *) *record;
140
488
    *record         = NULL;
141
142
488
    memory_free(
143
488
     internal_record );
144
488
  }
145
488
  return( 1 );
146
488
}
147
148
/* Reads the update journal entry list
149
 * Returns 1 if successful or -1 on error
150
 */
151
int libftxf_internal_record_read_update_journal_entry_list_data(
152
     libftxf_internal_record_t *internal_record,
153
     const uint8_t *record_data,
154
     size_t record_data_size,
155
     libcerror_error_t **error )
156
379
{
157
379
  libfusn_record_t *usn_record              = NULL;
158
379
  static char *function                     = "libftxf_internal_record_read_update_journal_entry_list_data";
159
379
  size_t record_data_offset                 = 0;
160
379
  uint64_t record_chain_next_lsn            = 0;
161
379
  uint32_t update_journal_entry_list_offset = 0;
162
379
  uint32_t update_journal_entry_list_size   = 0;
163
379
  uint32_t usn_record_size                  = 0;
164
165
#if defined( HAVE_DEBUG_OUTPUT )
166
  uint64_t value_64bit                      = 0;
167
#endif
168
169
379
  if( internal_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 internal record.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
379
  if( record_data == NULL )
181
0
  {
182
0
    libcerror_error_set(
183
0
     error,
184
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
185
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
186
0
     "%s: invalid record data.",
187
0
     function );
188
189
0
    return( -1 );
190
0
  }
191
379
  if( record_data_size > (size_t) SSIZE_MAX )
192
0
  {
193
0
    libcerror_error_set(
194
0
     error,
195
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
196
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
197
0
     "%s: invalid record data size value exceeds maximum.",
198
0
     function );
199
200
0
    return( -1 );
201
0
  }
202
379
  if( record_data_size < ( sizeof( ftxf_record_header_t ) + 16 ) )
203
7
  {
204
7
    libcerror_error_set(
205
7
     error,
206
7
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207
7
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
208
7
     "%s: invalid record data value too small.",
209
7
     function );
210
211
7
    return( -1 );
212
7
  }
213
372
  record_data_offset = sizeof( ftxf_record_header_t );
214
215
#if defined( HAVE_DEBUG_OUTPUT )
216
  if( libcnotify_verbose != 0 )
217
  {
218
    libcnotify_printf(
219
     "%s: journal entry list data:\n",
220
     function );
221
    libcnotify_print_data(
222
     &( record_data[ record_data_offset ] ),
223
     16,
224
     0 );
225
  }
226
#endif
227
372
  byte_stream_copy_to_uint64_little_endian(
228
372
   &( record_data[ record_data_offset ] ),
229
372
   record_chain_next_lsn );
230
231
372
  record_data_offset += 8;
232
233
372
  byte_stream_copy_to_uint32_little_endian(
234
372
   &( record_data[ record_data_offset ] ),
235
372
   update_journal_entry_list_offset );
236
237
372
  record_data_offset += 4;
238
239
372
  byte_stream_copy_to_uint32_little_endian(
240
372
   &( record_data[ record_data_offset ] ),
241
372
   update_journal_entry_list_size );
242
243
372
  record_data_offset += 4;
244
245
#if defined( HAVE_DEBUG_OUTPUT )
246
  if( libcnotify_verbose != 0 )
247
  {
248
    libcnotify_printf(
249
     "%s: next record lsn\t\t: 0x%08" PRIx64 "\n",
250
     function,
251
     record_chain_next_lsn );
252
253
    libcnotify_printf(
254
     "%s: list entries offset\t: 0x%08" PRIx32 "\n",
255
     function,
256
     update_journal_entry_list_offset );
257
258
    libcnotify_printf(
259
     "%s: list entries size\t\t: %" PRIu32 "\n",
260
     function,
261
     update_journal_entry_list_size );
262
263
    libcnotify_printf(
264
     "\n" );
265
  }
266
#endif
267
372
  if( ( (size_t) update_journal_entry_list_offset < record_data_offset )
268
372
   || ( (size_t) update_journal_entry_list_offset > record_data_size ) )
269
57
  {
270
57
    libcerror_error_set(
271
57
     error,
272
57
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
57
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
274
57
     "%s: update journal entry list offset value out of bounds.",
275
57
     function );
276
277
57
    goto on_error;
278
57
  }
279
315
  if( ( (size_t) update_journal_entry_list_offset + (size_t) update_journal_entry_list_size ) < record_data_size )
280
2
  {
281
2
    libcerror_error_set(
282
2
     error,
283
2
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
284
2
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
285
2
     "%s: update journal entry list size value out of bounds.",
286
2
     function );
287
288
2
    goto on_error;
289
2
  }
290
313
  if( (size_t) update_journal_entry_list_offset > record_data_offset )
291
51
  {
292
#if defined( HAVE_DEBUG_OUTPUT )
293
    if( libcnotify_verbose != 0 )
294
    {
295
      libcnotify_printf(
296
       "%s: update journal entry list trailing data:\n",
297
       function );
298
      libcnotify_print_data(
299
       &( record_data[ record_data_offset ] ),
300
       (size_t) update_journal_entry_list_offset - record_data_offset,
301
       0 );
302
    }
303
#endif
304
51
    record_data_offset = (size_t) update_journal_entry_list_offset;
305
51
  }
306
792
  while( record_data_offset < record_data_size )
307
702
  {
308
/* TODO print entry number */
309
310
#if defined( HAVE_DEBUG_OUTPUT )
311
    if( libcnotify_verbose != 0 )
312
    {
313
      libcnotify_printf(
314
       "%s: unknown:\n",
315
       function );
316
      libcnotify_print_data(
317
       &( record_data[ record_data_offset ] ),
318
       8,
319
       0 );
320
    }
321
#endif
322
#if defined( HAVE_DEBUG_OUTPUT )
323
    if( libcnotify_verbose != 0 )
324
    {
325
      byte_stream_copy_to_uint64_little_endian(
326
       &( record_data[ record_data_offset ] ),
327
       value_64bit );
328
      libcnotify_printf(
329
       "%s: unknown\t\t\t: 0x%08" PRIx64 "\n",
330
       function,
331
       value_64bit );
332
    }
333
#endif
334
702
    record_data_offset += 8;
335
336
702
    if( libfusn_record_initialize(
337
702
         &usn_record,
338
702
         error ) != 1 )
339
0
    {
340
0
      libcerror_error_set(
341
0
       error,
342
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
343
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
344
0
       "%s: unable to create USN record.",
345
0
       function );
346
347
0
      goto on_error;
348
0
    }
349
702
    if( libfusn_record_copy_from_byte_stream(
350
702
         usn_record,
351
702
         &( record_data[ record_data_offset ] ),
352
702
         record_data_size - record_data_offset,
353
702
         error ) != 1 )
354
223
    {
355
223
      libcerror_error_set(
356
223
       error,
357
223
       LIBCERROR_ERROR_DOMAIN_IO,
358
223
       LIBCERROR_IO_ERROR_READ_FAILED,
359
223
       "%s: unable to read USN record.",
360
223
       function );
361
362
223
      goto on_error;
363
223
    }
364
479
    if( libfusn_record_get_size(
365
479
         usn_record,
366
479
         &usn_record_size,
367
479
         error ) != 1 )
368
0
    {
369
0
      libcerror_error_set(
370
0
       error,
371
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
373
0
       "%s: unable to retrieve USN record size.",
374
0
       function );
375
376
0
      goto on_error;
377
0
    }
378
479
    record_data_offset += (size_t) usn_record_size;
379
380
/* TODO do something with USN records */
381
479
    if( libfusn_record_free(
382
479
         &usn_record,
383
479
         error ) != 1 )
384
0
    {
385
0
      libcerror_error_set(
386
0
       error,
387
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
388
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
389
0
       "%s: unable to free USN record.",
390
0
       function );
391
392
0
      goto on_error;
393
0
    }
394
479
  }
395
90
  return( 1 );
396
397
282
on_error:
398
282
  if( usn_record != NULL )
399
223
  {
400
223
    libfusn_record_free(
401
223
     &usn_record,
402
223
     NULL );
403
223
  }
404
282
  return( -1 );
405
313
}
406
407
/* Copies the record from the byte stream
408
 * Returns 1 if successful or -1 on error
409
 */
410
int libftxf_record_copy_from_byte_stream(
411
     libftxf_record_t *record,
412
     const uint8_t *byte_stream,
413
     size_t byte_stream_size,
414
     libcerror_error_t **error )
415
488
{
416
488
  libftxf_internal_record_t *internal_record = NULL;
417
488
  static char *function                      = "libftxf_record_read";
418
488
  size_t byte_stream_offset                  = 0;
419
488
  uint16_t record_type                       = 0;
420
488
  uint16_t name_offset                       = 0;
421
488
  uint16_t name_size                         = 0;
422
423
#if defined( HAVE_DEBUG_OUTPUT )
424
  uint64_t value_64bit                       = 0;
425
  uint32_t value_32bit                       = 0;
426
  uint16_t value_16bit                       = 0;
427
#endif
428
429
488
  if( record == NULL )
430
0
  {
431
0
    libcerror_error_set(
432
0
     error,
433
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
434
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
435
0
     "%s: invalid record.",
436
0
     function );
437
438
0
    return( -1 );
439
0
  }
440
488
  internal_record = (libftxf_internal_record_t *) record;
441
442
488
  if( byte_stream == NULL )
443
0
  {
444
0
    libcerror_error_set(
445
0
     error,
446
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
447
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
448
0
     "%s: invalid byte stream.",
449
0
     function );
450
451
0
    return( -1 );
452
0
  }
453
488
  if( byte_stream_size > (size_t) SSIZE_MAX )
454
0
  {
455
0
    libcerror_error_set(
456
0
     error,
457
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
458
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
459
0
     "%s: invalid byte stream size value exceeds maximum.",
460
0
     function );
461
462
0
    return( -1 );
463
0
  }
464
488
  if( byte_stream_size < sizeof( ftxf_record_header_t ) )
465
14
  {
466
14
    libcerror_error_set(
467
14
     error,
468
14
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
469
14
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
470
14
     "%s: invalid byte stream value too small.",
471
14
     function );
472
473
14
    return( -1 );
474
14
  }
475
#if defined( HAVE_DEBUG_OUTPUT )
476
  if( libcnotify_verbose != 0 )
477
  {
478
    libcnotify_printf(
479
     "%s: record header data:\n",
480
     function );
481
    libcnotify_print_data(
482
     byte_stream,
483
     sizeof( ftxf_record_header_t ),
484
     0 );
485
  }
486
#endif
487
474
  byte_stream_copy_to_uint16_little_endian(
488
474
   ( (ftxf_record_header_t *) byte_stream )->record_type,
489
474
   record_type );
490
491
474
  byte_stream_copy_to_uint32_little_endian(
492
474
   ( (ftxf_record_header_t *) byte_stream )->record_size,
493
474
   internal_record->size );
494
495
#if defined( HAVE_DEBUG_OUTPUT )
496
  if( libcnotify_verbose != 0 )
497
  {
498
    byte_stream_copy_to_uint32_little_endian(
499
     ( (ftxf_record_header_t *) byte_stream )->unknown1,
500
     value_32bit );
501
    libcnotify_printf(
502
     "%s: unknown1\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
503
     function,
504
     value_32bit );
505
506
    libcnotify_printf(
507
     "%s: record type\t\t\t\t\t: 0x%04" PRIx16 "\n",
508
     function,
509
     record_type );
510
511
    byte_stream_copy_to_uint16_little_endian(
512
     ( (ftxf_record_header_t *) byte_stream )->unknown2,
513
     value_16bit );
514
    libcnotify_printf(
515
     "%s: unknown2\t\t\t\t\t\t: 0x%04" PRIx16 "\n",
516
     function,
517
     value_16bit );
518
519
    byte_stream_copy_to_uint64_little_endian(
520
     ( (ftxf_record_header_t *) byte_stream )->file_identifier,
521
     value_64bit );
522
    libcnotify_printf(
523
     "%s: file identifier\t\t\t\t\t: 0x%08" PRIx64 "\n",
524
     function,
525
     value_64bit );
526
527
    byte_stream_copy_to_uint64_little_endian(
528
     ( (ftxf_record_header_t *) byte_stream )->file_reference,
529
     value_64bit );
530
    libcnotify_printf(
531
     "%s: file reference\t\t\t\t\t: MFT entry: %" PRIu64 ", sequence: %" PRIu64 "\n",
532
     function,
533
     value_64bit & 0xffffffffffffUL,
534
     value_64bit >> 48 );
535
536
    byte_stream_copy_to_uint32_little_endian(
537
     ( (ftxf_record_header_t *) byte_stream )->unknown4,
538
     value_32bit );
539
    libcnotify_printf(
540
     "%s: unknown4\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
541
     function,
542
     value_32bit );
543
544
    byte_stream_copy_to_uint32_little_endian(
545
     ( (ftxf_record_header_t *) byte_stream )->unknown5,
546
     value_32bit );
547
    libcnotify_printf(
548
     "%s: unknown5\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
549
     function,
550
     value_32bit );
551
552
    if( libftxf_debug_print_guid_value(
553
         function,
554
         "unknown6 guid\t\t\t\t\t",
555
         ( (ftxf_record_header_t *) byte_stream )->unknown6,
556
         16,
557
         LIBFGUID_ENDIAN_LITTLE,
558
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
559
         error ) != 1 )
560
    {
561
      libcerror_error_set(
562
       error,
563
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
564
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
565
       "%s: unable to print GUID value.",
566
       function );
567
568
      return( -1 );
569
    }
570
    byte_stream_copy_to_uint64_little_endian(
571
     ( (ftxf_record_header_t *) byte_stream )->unknown7,
572
     value_64bit );
573
    libcnotify_printf(
574
     "%s: unknown7\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
575
     function,
576
     value_64bit );
577
578
    if( libftxf_debug_print_filetime_value(
579
         function,
580
         "unknown8 filetime\t\t\t\t\t",
581
         ( (ftxf_record_header_t *) byte_stream )->unknown8,
582
         8,
583
         LIBFDATETIME_ENDIAN_LITTLE,
584
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
585
         error ) != 1 )
586
    {
587
      libcerror_error_set(
588
       error,
589
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
590
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
591
       "%s: unable to print FILETIME value.",
592
       function );
593
594
      return( -1 );
595
    }
596
    libcnotify_printf(
597
     "%s: record size\t\t\t\t\t: %" PRIu32 "\n",
598
     function,
599
     internal_record->size );
600
601
    byte_stream_copy_to_uint32_little_endian(
602
     ( (ftxf_record_header_t *) byte_stream )->unknown9,
603
     value_32bit );
604
    libcnotify_printf(
605
     "%s: unknown9\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
606
     function,
607
     value_32bit );
608
609
    byte_stream_copy_to_uint64_little_endian(
610
     ( (ftxf_record_header_t *) byte_stream )->unknown10,
611
     value_64bit );
612
    libcnotify_printf(
613
     "%s: unknown10\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
614
     function,
615
     value_64bit );
616
617
    libcnotify_printf(
618
     "\n" );
619
  }
620
#endif
621
474
  byte_stream_offset = sizeof( ftxf_record_header_t );
622
623
474
  if( ( (size_t) internal_record->size < sizeof( ftxf_record_header_t ) )
624
474
   || ( (size_t) internal_record->size > byte_stream_size ) )
625
77
  {
626
77
    libcerror_error_set(
627
77
     error,
628
77
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
629
77
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
630
77
     "%s: record size value out of bounds.",
631
77
     function );
632
633
77
    return( -1 );
634
77
  }
635
397
  switch( record_type )
636
397
  {
637
379
    case LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST:
638
379
      if( libftxf_internal_record_read_update_journal_entry_list_data(
639
379
           internal_record,
640
379
           byte_stream,
641
379
           (size_t) internal_record->size,
642
379
           error ) != 1 )
643
289
      {
644
289
        libcerror_error_set(
645
289
         error,
646
289
         LIBCERROR_ERROR_DOMAIN_IO,
647
289
         LIBCERROR_IO_ERROR_READ_FAILED,
648
289
         "%s: unable to read update journal entry list.",
649
289
         function );
650
651
289
        return( -1 );
652
289
      }
653
90
      break;
654
655
90
    default:
656
18
      break;
657
397
  }
658
/* TODO refactor */
659
108
  if( record_type == LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST )
660
90
  {
661
90
    return( 1 );
662
90
  }
663
#if defined( HAVE_DEBUG_OUTPUT )
664
  if( libcnotify_verbose != 0 )
665
  {
666
    libcnotify_printf(
667
     "%s: record data:\n",
668
     function );
669
    libcnotify_print_data(
670
     &( byte_stream[ byte_stream_offset ] ),
671
     (size_t) internal_record->size - sizeof( ftxf_record_header_t ),
672
     0 );
673
  }
674
#endif
675
#if defined( HAVE_DEBUG_OUTPUT )
676
  if( libcnotify_verbose != 0 )
677
  {
678
    byte_stream_copy_to_uint64_little_endian(
679
     &( byte_stream[ byte_stream_offset ] ),
680
     value_64bit );
681
    libcnotify_printf(
682
     "%s: unknown11\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
683
     function,
684
     value_64bit );
685
  }
686
#endif
687
18
  byte_stream_offset += 8;
688
689
18
  if( record_type != 0x00 )
690
17
  {
691
17
    byte_stream_copy_to_uint16_little_endian(
692
17
     &( byte_stream[ byte_stream_offset ] ),
693
17
     name_size );
694
695
#if defined( HAVE_DEBUG_OUTPUT )
696
    if( libcnotify_verbose != 0 )
697
    {
698
      libcnotify_printf(
699
       "%s: name size\t\t\t\t\t\t: %" PRIu16 "\n",
700
       function,
701
       name_size );
702
    }
703
#endif
704
17
    byte_stream_offset += 2;
705
706
17
    name_size *= 2;
707
708
17
    byte_stream_copy_to_uint16_little_endian(
709
17
     &( byte_stream[ byte_stream_offset ] ),
710
17
     name_offset );
711
712
#if defined( HAVE_DEBUG_OUTPUT )
713
    if( libcnotify_verbose != 0 )
714
    {
715
      libcnotify_printf(
716
       "%s: name offset\t\t\t\t\t: 0x%04" PRIx16 "\n",
717
       function,
718
       name_offset );
719
    }
720
#endif
721
17
    byte_stream_offset += 2;
722
723
#if defined( HAVE_DEBUG_OUTPUT )
724
    if( libcnotify_verbose != 0 )
725
    {
726
      byte_stream_copy_to_uint32_little_endian(
727
       &( byte_stream[ byte_stream_offset ] ),
728
       value_32bit );
729
      libcnotify_printf(
730
       "%s: unknown13\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
731
       function,
732
       value_32bit );
733
    }
734
#endif
735
17
    byte_stream_offset += 4;
736
17
  }
737
18
  if( record_type == 0x02 )
738
0
  {
739
#if defined( HAVE_DEBUG_OUTPUT )
740
    if( libcnotify_verbose != 0 )
741
    {
742
      libcnotify_printf(
743
       "...\n\n" );
744
    }
745
#endif
746
/* TODO print debug */
747
0
    byte_stream_offset += 24;
748
0
  }
749
18
  if( ( record_type == 0x02 )
750
18
   || ( record_type == 0x07 ) )
751
1
  {
752
#if defined( HAVE_DEBUG_OUTPUT )
753
    if( libcnotify_verbose != 0 )
754
    {
755
      if( libftxf_debug_print_filetime_value(
756
           function,
757
           "creation time\t\t\t\t\t",
758
           &( byte_stream[ byte_stream_offset ] ),
759
           8,
760
           LIBFDATETIME_ENDIAN_LITTLE,
761
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
762
           error ) != 1 )
763
      {
764
        libcerror_error_set(
765
         error,
766
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
767
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
768
         "%s: unable to print FILETIME value.",
769
         function );
770
771
        return( -1 );
772
      }
773
    }
774
#endif
775
1
    byte_stream_offset += 8;
776
777
#if defined( HAVE_DEBUG_OUTPUT )
778
    if( libcnotify_verbose != 0 )
779
    {
780
      if( libftxf_debug_print_filetime_value(
781
           function,
782
           "modification time\t\t\t\t\t",
783
           &( byte_stream[ byte_stream_offset ] ),
784
           8,
785
           LIBFDATETIME_ENDIAN_LITTLE,
786
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
787
           error ) != 1 )
788
      {
789
        libcerror_error_set(
790
         error,
791
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
792
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
793
         "%s: unable to print FILETIME value.",
794
         function );
795
796
        return( -1 );
797
      }
798
    }
799
#endif
800
1
    byte_stream_offset += 8;
801
802
#if defined( HAVE_DEBUG_OUTPUT )
803
    if( libcnotify_verbose != 0 )
804
    {
805
      if( libftxf_debug_print_filetime_value(
806
           function,
807
           "entry modification time\t\t\t\t",
808
           &( byte_stream[ byte_stream_offset ] ),
809
           8,
810
           LIBFDATETIME_ENDIAN_LITTLE,
811
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
812
           error ) != 1 )
813
      {
814
        libcerror_error_set(
815
         error,
816
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
817
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
818
         "%s: unable to print FILETIME value.",
819
         function );
820
821
        return( -1 );
822
      }
823
    }
824
#endif
825
1
    byte_stream_offset += 8;
826
827
#if defined( HAVE_DEBUG_OUTPUT )
828
    if( libcnotify_verbose != 0 )
829
    {
830
      if( libftxf_debug_print_filetime_value(
831
           function,
832
           "access time\t\t\t\t\t",
833
           &( byte_stream[ byte_stream_offset ] ),
834
           8,
835
           LIBFDATETIME_ENDIAN_LITTLE,
836
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
837
           error ) != 1 )
838
      {
839
        libcerror_error_set(
840
         error,
841
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
842
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
843
         "%s: unable to print FILETIME value.",
844
         function );
845
846
        return( -1 );
847
      }
848
    }
849
#endif
850
1
    byte_stream_offset += 8;
851
852
#if defined( HAVE_DEBUG_OUTPUT )
853
    if( libcnotify_verbose != 0 )
854
    {
855
      byte_stream_copy_to_uint64_little_endian(
856
       &( byte_stream[ byte_stream_offset ] ),
857
       value_64bit );
858
      libcnotify_printf(
859
       "%s: allocated file size\t\t\t\t: %" PRIu64 "\n",
860
       function,
861
       value_64bit );
862
    }
863
#endif
864
1
    byte_stream_offset += 8;
865
866
#if defined( HAVE_DEBUG_OUTPUT )
867
    if( libcnotify_verbose != 0 )
868
    {
869
      byte_stream_copy_to_uint64_little_endian(
870
       &( byte_stream[ byte_stream_offset ] ),
871
       value_64bit );
872
      libcnotify_printf(
873
       "%s: file size\t\t\t\t\t\t: %" PRIu64 "\n",
874
       function,
875
       value_64bit );
876
    }
877
#endif
878
1
    byte_stream_offset += 8;
879
880
#if defined( HAVE_DEBUG_OUTPUT )
881
    if( libcnotify_verbose != 0 )
882
    {
883
      byte_stream_copy_to_uint32_little_endian(
884
       &( byte_stream[ byte_stream_offset ] ),
885
       value_32bit );
886
      libcnotify_printf(
887
       "%s: file attribute flags\t\t\t\t: 0x%08" PRIx32 "\n",
888
       function,
889
       value_32bit );
890
      libftxf_debug_print_file_attribute_flags(
891
       value_32bit );
892
      libcnotify_printf(
893
       "\n" );
894
    }
895
#endif
896
1
    byte_stream_offset += 4;
897
898
#if defined( HAVE_DEBUG_OUTPUT )
899
    if( libcnotify_verbose != 0 )
900
    {
901
      libcnotify_printf(
902
       "...\n\n" );
903
    }
904
#endif
905
1
  }
906
17
  else if( record_type == 0x0b )
907
0
  {
908
#if defined( HAVE_DEBUG_OUTPUT )
909
    if( libcnotify_verbose != 0 )
910
    {
911
      byte_stream_copy_to_uint64_little_endian(
912
       &( byte_stream[ byte_stream_offset ] ),
913
       value_64bit );
914
      libcnotify_printf(
915
       "%s: unknown14\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
916
       function,
917
       value_64bit );
918
    }
919
#endif
920
0
    byte_stream_offset += 8;
921
0
  }
922
#if defined( HAVE_DEBUG_OUTPUT )
923
  else if( libcnotify_verbose != 0 )
924
  {
925
    libcnotify_printf(
926
     "...\n\n" );
927
  }
928
#endif
929
18
  if( record_type == 0x15 )
930
0
  {
931
0
    return( 1 );
932
0
  }
933
18
  if( name_size > 0 )
934
17
  {
935
    /* TODO check if name size is within bounds */
936
    /* TODO check if name offset is within bounds */
937
938
#if defined( HAVE_DEBUG_OUTPUT )
939
    if( libcnotify_verbose != 0 )
940
    {
941
      if( libftxf_debug_print_utf16_string_value(
942
           function,
943
           "name\t\t\t\t\t\t",
944
           &( byte_stream[ name_offset ] ),
945
           name_size,
946
           LIBUNA_ENDIAN_LITTLE,
947
           error ) != 1 )
948
      {
949
        libcerror_error_set(
950
         error,
951
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
952
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
953
         "%s: unable to print UTF-16 string value.",
954
         function );
955
956
        return( -1 );
957
      }
958
    }
959
#endif
960
17
  }
961
#if defined( HAVE_DEBUG_OUTPUT )
962
  if( libcnotify_verbose != 0 )
963
  {
964
    libcnotify_printf(
965
     "\n" );
966
  }
967
#endif
968
18
  return( 1 );
969
18
}
970