Coverage Report

Created: 2026-07-10 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libftxf/libftxf/libftxf_record.c
Line
Count
Source
1
/*
2
 * Record functions
3
 *
4
 * Copyright (C) 2010-2026, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <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
484
{
50
484
  libftxf_internal_record_t *internal_record = NULL;
51
484
  static char *function                      = "libftxf_record_initialize";
52
53
484
  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
484
  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
484
  internal_record = memory_allocate_structure(
76
484
                     libftxf_internal_record_t );
77
78
484
  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
484
  if( memory_set(
90
484
       internal_record,
91
484
       0,
92
484
       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
484
  *record = (libftxf_record_t *) internal_record;
104
105
484
  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
484
}
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
484
{
123
484
  libftxf_internal_record_t *internal_record = NULL;
124
484
  static char *function                      = "libftxf_record_free";
125
126
484
  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
484
  if( *record != NULL )
138
484
  {
139
484
    internal_record = (libftxf_internal_record_t *) *record;
140
484
    *record         = NULL;
141
142
484
    memory_free(
143
484
     internal_record );
144
484
  }
145
484
  return( 1 );
146
484
}
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
381
{
157
381
  libfusn_record_t *usn_record              = NULL;
158
381
  static char *function                     = "libftxf_internal_record_read_update_journal_entry_list_data";
159
381
  size_t record_data_offset                 = 0;
160
381
  uint64_t record_chain_next_lsn            = 0;
161
381
  uint32_t update_journal_entry_list_offset = 0;
162
381
  uint32_t update_journal_entry_list_size   = 0;
163
381
  uint32_t usn_record_size                  = 0;
164
165
#if defined( HAVE_DEBUG_OUTPUT )
166
  uint64_t value_64bit                      = 0;
167
#endif
168
169
381
  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
381
  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
381
  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
381
  if( record_data_size < ( sizeof( ftxf_record_header_t ) + 16 ) )
203
14
  {
204
14
    libcerror_error_set(
205
14
     error,
206
14
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207
14
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
208
14
     "%s: invalid record data value too small.",
209
14
     function );
210
211
14
    return( -1 );
212
14
  }
213
367
  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
367
  byte_stream_copy_to_uint64_little_endian(
228
367
   &( record_data[ record_data_offset ] ),
229
367
   record_chain_next_lsn );
230
231
367
  record_data_offset += 8;
232
233
367
  byte_stream_copy_to_uint32_little_endian(
234
367
   &( record_data[ record_data_offset ] ),
235
367
   update_journal_entry_list_offset );
236
237
367
  record_data_offset += 4;
238
239
367
  byte_stream_copy_to_uint32_little_endian(
240
367
   &( record_data[ record_data_offset ] ),
241
367
   update_journal_entry_list_size );
242
243
367
  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
367
  if( ( (size_t) update_journal_entry_list_offset < record_data_offset )
268
357
   || ( (size_t) update_journal_entry_list_offset > record_data_size ) )
269
60
  {
270
60
    libcerror_error_set(
271
60
     error,
272
60
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
273
60
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
274
60
     "%s: update journal entry list offset value out of bounds.",
275
60
     function );
276
277
60
    goto on_error;
278
60
  }
279
307
  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
305
  if( (size_t) update_journal_entry_list_offset > record_data_offset )
291
48
  {
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
48
    record_data_offset = (size_t) update_journal_entry_list_offset;
305
48
  }
306
826
  while( record_data_offset < record_data_size )
307
740
  {
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
740
    record_data_offset += 8;
335
336
740
    if( libfusn_record_initialize(
337
740
         &usn_record,
338
740
         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
740
    if( libfusn_record_copy_from_byte_stream(
350
740
         usn_record,
351
740
         &( record_data[ record_data_offset ] ),
352
740
         record_data_size - record_data_offset,
353
740
         error ) != 1 )
354
219
    {
355
219
      libcerror_error_set(
356
219
       error,
357
219
       LIBCERROR_ERROR_DOMAIN_IO,
358
219
       LIBCERROR_IO_ERROR_READ_FAILED,
359
219
       "%s: unable to read USN record.",
360
219
       function );
361
362
219
      goto on_error;
363
219
    }
364
521
    if( libfusn_record_get_size(
365
521
         usn_record,
366
521
         &usn_record_size,
367
521
         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
521
    record_data_offset += (size_t) usn_record_size;
379
380
/* TODO do something with USN records */
381
521
    if( libfusn_record_free(
382
521
         &usn_record,
383
521
         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
521
  }
395
86
  return( 1 );
396
397
281
on_error:
398
281
  if( usn_record != NULL )
399
219
  {
400
219
    libfusn_record_free(
401
219
     &usn_record,
402
219
     NULL );
403
219
  }
404
281
  return( -1 );
405
305
}
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
484
{
416
484
  libftxf_internal_record_t *internal_record = NULL;
417
484
  static char *function                      = "libftxf_record_read";
418
484
  size_t byte_stream_offset                  = 0;
419
484
  uint16_t record_type                       = 0;
420
484
  uint16_t name_offset                       = 0;
421
484
  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
484
  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
484
  internal_record = (libftxf_internal_record_t *) record;
441
442
484
  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
484
  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
484
  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
470
  byte_stream_copy_to_uint16_little_endian(
488
470
   ( (ftxf_record_header_t *) byte_stream )->record_type,
489
470
   record_type );
490
491
470
  byte_stream_copy_to_uint32_little_endian(
492
470
   ( (ftxf_record_header_t *) byte_stream )->record_size,
493
470
   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
470
  byte_stream_offset = sizeof( ftxf_record_header_t );
622
623
470
  if( ( (size_t) internal_record->size < sizeof( ftxf_record_header_t ) )
624
461
   || ( (size_t) internal_record->size > byte_stream_size ) )
625
56
  {
626
56
    libcerror_error_set(
627
56
     error,
628
56
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
629
56
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
630
56
     "%s: record size value out of bounds.",
631
56
     function );
632
633
56
    return( -1 );
634
56
  }
635
414
  switch( record_type )
636
414
  {
637
381
    case LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST:
638
381
      if( libftxf_internal_record_read_update_journal_entry_list_data(
639
381
           internal_record,
640
381
           byte_stream,
641
381
           (size_t) internal_record->size,
642
381
           error ) != 1 )
643
295
      {
644
295
        libcerror_error_set(
645
295
         error,
646
295
         LIBCERROR_ERROR_DOMAIN_IO,
647
295
         LIBCERROR_IO_ERROR_READ_FAILED,
648
295
         "%s: unable to read update journal entry list.",
649
295
         function );
650
651
295
        return( -1 );
652
295
      }
653
86
      break;
654
655
86
    default:
656
33
      break;
657
414
  }
658
/* TODO refactor */
659
119
  if( record_type == LIBFTXF_RECORD_TYPE_UPDATE_JOURNAL_ENTRIES_LIST )
660
86
  {
661
86
    return( 1 );
662
86
  }
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
33
  byte_stream_offset += 8;
688
689
33
  if( record_type != 0x00 )
690
31
  {
691
31
    byte_stream_copy_to_uint16_little_endian(
692
31
     &( byte_stream[ byte_stream_offset ] ),
693
31
     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
31
    byte_stream_offset += 2;
705
706
31
    name_size *= 2;
707
708
31
    byte_stream_copy_to_uint16_little_endian(
709
31
     &( byte_stream[ byte_stream_offset ] ),
710
31
     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
      byte_stream_offset += 2;
721
722
      byte_stream_copy_to_uint32_little_endian(
723
       &( byte_stream[ byte_stream_offset ] ),
724
       value_32bit );
725
      libcnotify_printf(
726
       "%s: unknown13\t\t\t\t\t\t: 0x%08" PRIx32 "\n",
727
       function,
728
       value_32bit );
729
730
      byte_stream_offset += 4;
731
    }
732
#endif
733
31
  }
734
33
  if( record_type == 0x02 )
735
0
  {
736
#if defined( HAVE_DEBUG_OUTPUT )
737
    if( libcnotify_verbose != 0 )
738
    {
739
      libcnotify_printf(
740
       "...\n\n" );
741
742
/* TODO print debug */
743
      byte_stream_offset += 24;
744
    }
745
#endif
746
0
  }
747
33
  if( ( record_type == 0x02 )
748
33
   || ( record_type == 0x07 ) )
749
0
  {
750
#if defined( HAVE_DEBUG_OUTPUT )
751
    if( libcnotify_verbose != 0 )
752
    {
753
      if( libftxf_debug_print_filetime_value(
754
           function,
755
           "creation time\t\t\t\t\t",
756
           &( byte_stream[ byte_stream_offset ] ),
757
           8,
758
           LIBFDATETIME_ENDIAN_LITTLE,
759
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
760
           error ) != 1 )
761
      {
762
        libcerror_error_set(
763
         error,
764
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
765
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
766
         "%s: unable to print FILETIME value.",
767
         function );
768
769
        return( -1 );
770
      }
771
      byte_stream_offset += 8;
772
773
      if( libftxf_debug_print_filetime_value(
774
           function,
775
           "modification time\t\t\t\t\t",
776
           &( byte_stream[ byte_stream_offset ] ),
777
           8,
778
           LIBFDATETIME_ENDIAN_LITTLE,
779
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
780
           error ) != 1 )
781
      {
782
        libcerror_error_set(
783
         error,
784
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
785
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
786
         "%s: unable to print FILETIME value.",
787
         function );
788
789
        return( -1 );
790
      }
791
      byte_stream_offset += 8;
792
793
      if( libftxf_debug_print_filetime_value(
794
           function,
795
           "entry modification time\t\t\t\t",
796
           &( byte_stream[ byte_stream_offset ] ),
797
           8,
798
           LIBFDATETIME_ENDIAN_LITTLE,
799
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
800
           error ) != 1 )
801
      {
802
        libcerror_error_set(
803
         error,
804
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
805
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
806
         "%s: unable to print FILETIME value.",
807
         function );
808
809
        return( -1 );
810
      }
811
      byte_stream_offset += 8;
812
813
      if( libftxf_debug_print_filetime_value(
814
           function,
815
           "access time\t\t\t\t\t",
816
           &( byte_stream[ byte_stream_offset ] ),
817
           8,
818
           LIBFDATETIME_ENDIAN_LITTLE,
819
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
820
           error ) != 1 )
821
      {
822
        libcerror_error_set(
823
         error,
824
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
825
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
826
         "%s: unable to print FILETIME value.",
827
         function );
828
829
        return( -1 );
830
      }
831
      byte_stream_offset += 8;
832
833
      byte_stream_copy_to_uint64_little_endian(
834
       &( byte_stream[ byte_stream_offset ] ),
835
       value_64bit );
836
      libcnotify_printf(
837
       "%s: allocated file size\t\t\t\t: %" PRIu64 "\n",
838
       function,
839
       value_64bit );
840
841
      byte_stream_offset += 8;
842
843
      byte_stream_copy_to_uint64_little_endian(
844
       &( byte_stream[ byte_stream_offset ] ),
845
       value_64bit );
846
      libcnotify_printf(
847
       "%s: file size\t\t\t\t\t\t: %" PRIu64 "\n",
848
       function,
849
       value_64bit );
850
851
      byte_stream_offset += 8;
852
853
      byte_stream_copy_to_uint32_little_endian(
854
       &( byte_stream[ byte_stream_offset ] ),
855
       value_32bit );
856
      libcnotify_printf(
857
       "%s: file attribute flags\t\t\t\t: 0x%08" PRIx32 "\n",
858
       function,
859
       value_32bit );
860
      libftxf_debug_print_file_attribute_flags(
861
       value_32bit );
862
      libcnotify_printf(
863
       "\n" );
864
865
      byte_stream_offset += 4;
866
867
      libcnotify_printf(
868
       "...\n\n" );
869
    }
870
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
871
0
  }
872
33
  else if( record_type == 0x0b )
873
1
  {
874
#if defined( HAVE_DEBUG_OUTPUT )
875
    if( libcnotify_verbose != 0 )
876
    {
877
      byte_stream_copy_to_uint64_little_endian(
878
       &( byte_stream[ byte_stream_offset ] ),
879
       value_64bit );
880
      libcnotify_printf(
881
       "%s: unknown14\t\t\t\t\t\t: 0x%08" PRIx64 "\n",
882
       function,
883
       value_64bit );
884
885
      byte_stream_offset += 8;
886
    }
887
#endif
888
1
  }
889
#if defined( HAVE_DEBUG_OUTPUT )
890
  else if( libcnotify_verbose != 0 )
891
  {
892
    libcnotify_printf(
893
     "...\n\n" );
894
  }
895
#endif
896
33
  if( record_type == 0x15 )
897
1
  {
898
1
    return( 1 );
899
1
  }
900
32
  if( name_size > 0 )
901
28
  {
902
    /* TODO check if name size is within bounds */
903
    /* TODO check if name offset is within bounds */
904
905
#if defined( HAVE_DEBUG_OUTPUT )
906
    if( libcnotify_verbose != 0 )
907
    {
908
      if( libftxf_debug_print_utf16_string_value(
909
           function,
910
           "name\t\t\t\t\t\t",
911
           &( byte_stream[ name_offset ] ),
912
           name_size,
913
           LIBUNA_ENDIAN_LITTLE,
914
           error ) != 1 )
915
      {
916
        libcerror_error_set(
917
         error,
918
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
919
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
920
         "%s: unable to print UTF-16 string value.",
921
         function );
922
923
        return( -1 );
924
      }
925
    }
926
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
927
28
  }
928
#if defined( HAVE_DEBUG_OUTPUT )
929
  if( libcnotify_verbose != 0 )
930
  {
931
    libcnotify_printf(
932
     "\n" );
933
  }
934
#endif
935
32
  return( 1 );
936
33
}
937