Coverage Report

Created: 2025-06-13 07:22

/src/libfsntfs/libfsntfs/libfsntfs_file_name_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File name attribute ($FILE_NAME) values 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 "libfsntfs_debug.h"
31
#include "libfsntfs_definitions.h"
32
#include "libfsntfs_file_name_values.h"
33
#include "libfsntfs_libcdata.h"
34
#include "libfsntfs_libcerror.h"
35
#include "libfsntfs_libcnotify.h"
36
#include "libfsntfs_libfdatetime.h"
37
#include "libfsntfs_libuna.h"
38
#include "libfsntfs_mft_attribute.h"
39
#include "libfsntfs_name.h"
40
41
#include "fsntfs_file_name.h"
42
43
/* Creates file name values
44
 * Make sure the value file_name_values is referencing, is set to NULL
45
 * Returns 1 if successful or -1 on error
46
 */
47
int libfsntfs_file_name_values_initialize(
48
     libfsntfs_file_name_values_t **file_name_values,
49
     libcerror_error_t **error )
50
6.58k
{
51
6.58k
  static char *function = "libfsntfs_file_name_values_initialize";
52
53
6.58k
  if( file_name_values == 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 file name values.",
60
0
     function );
61
62
0
    return( -1 );
63
0
  }
64
6.58k
  if( *file_name_values != 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 file name values value already set.",
71
0
     function );
72
73
0
    return( -1 );
74
0
  }
75
6.58k
  *file_name_values = memory_allocate_structure(
76
6.58k
                       libfsntfs_file_name_values_t );
77
78
6.58k
  if( *file_name_values == 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 file name values.",
85
0
     function );
86
87
0
    goto on_error;
88
0
  }
89
6.58k
  if( memory_set(
90
6.58k
       *file_name_values,
91
6.58k
       0,
92
6.58k
       sizeof( libfsntfs_file_name_values_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 file name values.",
99
0
     function );
100
101
0
    goto on_error;
102
0
  }
103
6.58k
  return( 1 );
104
105
0
on_error:
106
0
  if( *file_name_values != NULL )
107
0
  {
108
0
    memory_free(
109
0
     *file_name_values );
110
111
0
    *file_name_values = NULL;
112
0
  }
113
0
  return( -1 );
114
6.58k
}
115
116
/* Frees file name values
117
 * Returns 1 if successful or -1 on error
118
 */
119
int libfsntfs_file_name_values_free(
120
     libfsntfs_file_name_values_t **file_name_values,
121
     libcerror_error_t **error )
122
6.62k
{
123
6.62k
  static char *function = "libfsntfs_file_name_values_free";
124
125
6.62k
  if( file_name_values == NULL )
126
0
  {
127
0
    libcerror_error_set(
128
0
     error,
129
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
130
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
131
0
     "%s: invalid file name values.",
132
0
     function );
133
134
0
    return( -1 );
135
0
  }
136
6.62k
  if( *file_name_values != NULL )
137
6.62k
  {
138
6.62k
    if( ( *file_name_values )->name != NULL )
139
6.54k
    {
140
6.54k
      memory_free(
141
6.54k
       ( *file_name_values )->name );
142
6.54k
    }
143
6.62k
    memory_free(
144
6.62k
     *file_name_values );
145
146
6.62k
    *file_name_values = NULL;
147
6.62k
  }
148
6.62k
  return( 1 );
149
6.62k
}
150
151
/* Clones file name values
152
 * Returns 1 if successful or -1 on error
153
 */
154
int libfsntfs_file_name_values_clone(
155
     libfsntfs_file_name_values_t **destination_file_name_values,
156
     libfsntfs_file_name_values_t *source_file_name_values,
157
     libcerror_error_t **error )
158
82
{
159
82
  static char *function = "libfsntfs_file_name_values_clone";
160
161
82
  if( destination_file_name_values == NULL )
162
0
  {
163
0
    libcerror_error_set(
164
0
     error,
165
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
166
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
167
0
     "%s: invalid file name values.",
168
0
     function );
169
170
0
    return( -1 );
171
0
  }
172
82
  if( *destination_file_name_values != NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
177
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
178
0
     "%s: invalid destination file name values value already set.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
82
  if( source_file_name_values == NULL )
184
41
  {
185
41
    *destination_file_name_values = source_file_name_values;
186
187
41
    return( 1 );
188
41
  }
189
41
  *destination_file_name_values = memory_allocate_structure(
190
41
                                   libfsntfs_file_name_values_t );
191
192
41
  if( *destination_file_name_values == NULL )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
197
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
198
0
     "%s: unable to create destination file name values.",
199
0
     function );
200
201
0
    goto on_error;
202
0
  }
203
41
  if( memory_copy(
204
41
       *destination_file_name_values,
205
41
       source_file_name_values,
206
41
       sizeof( libfsntfs_file_name_values_t ) ) == NULL )
207
0
  {
208
0
    libcerror_error_set(
209
0
     error,
210
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
211
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
212
0
     "%s: unable to copy source file name values to destination.",
213
0
     function );
214
215
0
    goto on_error;
216
0
  }
217
41
  ( *destination_file_name_values )->name      = NULL;
218
41
  ( *destination_file_name_values )->name_size = 0;
219
220
41
  if( libfsntfs_file_name_values_set_name(
221
41
       *destination_file_name_values,
222
41
       source_file_name_values->name,
223
41
       source_file_name_values->name_size,
224
41
       error ) != 1 )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
230
0
     "%s: unable to set destination name.",
231
0
     function );
232
233
0
    goto on_error;
234
0
  }
235
41
  return( 1 );
236
237
0
on_error:
238
0
  if( *destination_file_name_values != NULL )
239
0
  {
240
0
    memory_free(
241
0
     *destination_file_name_values );
242
243
0
    *destination_file_name_values = NULL;
244
0
  }
245
0
  return( -1 );
246
41
}
247
248
/* Sets the name
249
 * The size should include the end of string character
250
 * Returns 1 if successful or -1 on error
251
 */
252
int libfsntfs_file_name_values_set_name(
253
     libfsntfs_file_name_values_t *file_name_values,
254
     const uint8_t *utf16_stream,
255
     size_t utf16_stream_size,
256
     libcerror_error_t **error )
257
6.54k
{
258
6.54k
  static char *function = "libfsntfs_file_name_values_set_name";
259
260
6.54k
  if( file_name_values == NULL )
261
0
  {
262
0
    libcerror_error_set(
263
0
     error,
264
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
265
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
266
0
     "%s: invalid file name values.",
267
0
     function );
268
269
0
    return( -1 );
270
0
  }
271
6.54k
  if( file_name_values->name != NULL )
272
0
  {
273
0
    libcerror_error_set(
274
0
     error,
275
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
276
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
277
0
     "%s: invalid file name values - name value already set.",
278
0
     function );
279
280
0
    return( -1 );
281
0
  }
282
6.54k
  if( utf16_stream == NULL )
283
0
  {
284
0
    libcerror_error_set(
285
0
     error,
286
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
287
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
288
0
     "%s: invalid UTF-16 stream.",
289
0
     function );
290
291
0
    return( -1 );
292
0
  }
293
6.54k
  if( ( utf16_stream_size == 0 )
294
6.54k
   || ( utf16_stream_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
295
0
  {
296
0
    libcerror_error_set(
297
0
     error,
298
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
299
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
300
0
     "%s: invalid UTF-16 stream size value out of bounds.",
301
0
     function );
302
303
0
    return( -1 );
304
0
  }
305
6.54k
  file_name_values->name = (uint8_t *) memory_allocate(
306
6.54k
                                        sizeof( uint8_t ) * (size_t) utf16_stream_size );
307
308
6.54k
  if( file_name_values->name == NULL )
309
0
  {
310
0
    libcerror_error_set(
311
0
     error,
312
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
313
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
314
0
     "%s: unable to create name.",
315
0
     function );
316
317
0
    goto on_error;
318
0
  }
319
6.54k
  if( memory_copy(
320
6.54k
       file_name_values->name,
321
6.54k
       utf16_stream,
322
6.54k
       utf16_stream_size ) == NULL )
323
0
  {
324
0
    libcerror_error_set(
325
0
     error,
326
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
327
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
328
0
     "%s: unable to copy name.",
329
0
     function );
330
331
0
    goto on_error;
332
0
  }
333
6.54k
  file_name_values->name_size = utf16_stream_size;
334
335
6.54k
  return( 1 );
336
337
0
on_error:
338
0
  if( file_name_values->name != NULL )
339
0
  {
340
0
    memory_free(
341
0
     file_name_values->name );
342
343
0
    file_name_values->name = NULL;
344
0
  }
345
0
  file_name_values->name_size = 0;
346
347
0
  return( -1 );
348
6.54k
}
349
350
/* Reads the file name values
351
 * Returns 1 if successful or -1 on error
352
 */
353
int libfsntfs_file_name_values_read_data(
354
     libfsntfs_file_name_values_t *file_name_values,
355
     const uint8_t *data,
356
     size_t data_size,
357
     libcerror_error_t **error )
358
6.57k
{
359
6.57k
  static char *function = "libfsntfs_file_name_values_read_data";
360
6.57k
  size_t data_offset    = 0;
361
6.57k
  uint16_t name_size    = 0;
362
363
#if defined( HAVE_DEBUG_OUTPUT )
364
  uint64_t value_64bit  = 0;
365
  uint32_t value_32bit  = 0;
366
#endif
367
368
6.57k
  if( file_name_values == NULL )
369
0
  {
370
0
    libcerror_error_set(
371
0
     error,
372
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
373
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
374
0
     "%s: invalid file name values.",
375
0
     function );
376
377
0
    return( -1 );
378
0
  }
379
6.57k
  if( file_name_values->name != NULL )
380
0
  {
381
0
    libcerror_error_set(
382
0
     error,
383
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
384
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
385
0
     "%s: invalid file name values - name already set.",
386
0
     function );
387
388
0
    return( -1 );
389
0
  }
390
6.57k
  if( data == NULL )
391
14
  {
392
14
    libcerror_error_set(
393
14
     error,
394
14
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
395
14
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
396
14
     "%s: invalid data.",
397
14
     function );
398
399
14
    return( -1 );
400
14
  }
401
6.56k
  if( data_size > (size_t) SSIZE_MAX )
402
0
  {
403
0
    libcerror_error_set(
404
0
     error,
405
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
406
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
407
0
     "%s: invalid data size value exceeds maximum.",
408
0
     function );
409
410
0
    return( -1 );
411
0
  }
412
6.56k
  if( data_size < sizeof( fsntfs_file_name_t ) )
413
19
  {
414
19
    libcerror_error_set(
415
19
     error,
416
19
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
417
19
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
418
19
     "%s: unsupported data size value too small.",
419
19
     function );
420
421
19
    return( -1 );
422
19
  }
423
#if defined( HAVE_DEBUG_OUTPUT )
424
  if( libcnotify_verbose != 0 )
425
  {
426
    libcnotify_printf(
427
     "%s: file name data:\n",
428
     function );
429
    libcnotify_print_data(
430
     data,
431
     data_size,
432
     0 );
433
  }
434
#endif
435
6.54k
  byte_stream_copy_to_uint64_little_endian(
436
6.54k
   ( (fsntfs_file_name_t *) data )->parent_file_reference,
437
6.54k
   file_name_values->parent_file_reference );
438
439
6.54k
  byte_stream_copy_to_uint64_little_endian(
440
6.54k
   ( (fsntfs_file_name_t *) data )->creation_time,
441
6.54k
   file_name_values->creation_time );
442
443
6.54k
  byte_stream_copy_to_uint64_little_endian(
444
6.54k
   ( (fsntfs_file_name_t *) data )->modification_time,
445
6.54k
   file_name_values->modification_time );
446
447
6.54k
  byte_stream_copy_to_uint64_little_endian(
448
6.54k
   ( (fsntfs_file_name_t *) data )->access_time,
449
6.54k
   file_name_values->access_time );
450
451
6.54k
  byte_stream_copy_to_uint64_little_endian(
452
6.54k
   ( (fsntfs_file_name_t *) data )->entry_modification_time,
453
6.54k
   file_name_values->entry_modification_time );
454
455
6.54k
  byte_stream_copy_to_uint32_little_endian(
456
6.54k
   ( (fsntfs_file_name_t *) data )->file_attribute_flags,
457
6.54k
   file_name_values->file_attribute_flags );
458
459
6.54k
  name_size = (uint16_t) ( (fsntfs_file_name_t *) data )->name_size;
460
461
6.54k
  file_name_values->name_space = ( (fsntfs_file_name_t *) data )->name_space;
462
463
#if defined( HAVE_DEBUG_OUTPUT )
464
  if( libcnotify_verbose != 0 )
465
  {
466
    libcnotify_printf(
467
     "%s: parent file reference\t\t: %" PRIu64 "-%" PRIu64 "\n",
468
     function,
469
     file_name_values->parent_file_reference & 0xffffffffffffUL,
470
     file_name_values->parent_file_reference >> 48 );
471
472
    if( libfsntfs_debug_print_filetime_value(
473
         function,
474
         "creation time\t\t\t",
475
         ( (fsntfs_file_name_t *) data )->creation_time,
476
         8,
477
         LIBFDATETIME_ENDIAN_LITTLE,
478
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
479
         error ) != 1 )
480
    {
481
      libcerror_error_set(
482
       error,
483
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
484
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
485
       "%s: unable to print FILETIME value.",
486
       function );
487
488
      goto on_error;
489
    }
490
    if( libfsntfs_debug_print_filetime_value(
491
         function,
492
         "modification time\t\t\t",
493
         ( (fsntfs_file_name_t *) data )->modification_time,
494
         8,
495
         LIBFDATETIME_ENDIAN_LITTLE,
496
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
497
         error ) != 1 )
498
    {
499
      libcerror_error_set(
500
       error,
501
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
502
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
503
       "%s: unable to print FILETIME value.",
504
       function );
505
506
      goto on_error;
507
    }
508
    if( libfsntfs_debug_print_filetime_value(
509
         function,
510
         "entry modification time\t\t",
511
         ( (fsntfs_file_name_t *) data )->entry_modification_time,
512
         8,
513
         LIBFDATETIME_ENDIAN_LITTLE,
514
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
515
         error ) != 1 )
516
    {
517
      libcerror_error_set(
518
       error,
519
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
521
       "%s: unable to print FILETIME value.",
522
       function );
523
524
      goto on_error;
525
    }
526
    if( libfsntfs_debug_print_filetime_value(
527
         function,
528
         "access time\t\t\t",
529
         ( (fsntfs_file_name_t *) data )->access_time,
530
         8,
531
         LIBFDATETIME_ENDIAN_LITTLE,
532
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
533
         error ) != 1 )
534
    {
535
      libcerror_error_set(
536
       error,
537
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
538
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
539
       "%s: unable to print FILETIME value.",
540
       function );
541
542
      goto on_error;
543
    }
544
    byte_stream_copy_to_uint64_little_endian(
545
     ( (fsntfs_file_name_t *) data )->allocated_data_size,
546
     value_64bit );
547
    libcnotify_printf(
548
     "%s: allocated data size\t\t: %" PRIu64 "\n",
549
     function,
550
     value_64bit );
551
552
    byte_stream_copy_to_uint64_little_endian(
553
     ( (fsntfs_file_name_t *) data )->data_size,
554
     value_64bit );
555
    libcnotify_printf(
556
     "%s: data size\t\t\t\t: %" PRIu64 "\n",
557
     function,
558
     value_64bit );
559
560
    libcnotify_printf(
561
     "%s: file attribute flags\t\t: 0x%08" PRIx32 "\n",
562
     function,
563
     file_name_values->file_attribute_flags );
564
    libfsntfs_debug_print_file_attribute_flags(
565
     file_name_values->file_attribute_flags );
566
    libcnotify_printf(
567
     "\n" );
568
569
    byte_stream_copy_to_uint32_little_endian(
570
     ( (fsntfs_file_name_t *) data )->extended_data,
571
     value_32bit );
572
    libcnotify_printf(
573
     "%s: extended data\t\t\t: 0x%08" PRIx32 "\n",
574
     function,
575
     value_32bit );
576
577
    libcnotify_printf(
578
     "%s: name size\t\t\t\t: %" PRIu16 "\n",
579
     function,
580
     name_size );
581
582
    libcnotify_printf(
583
     "%s: name space\t\t\t: %" PRIu8 " (%s)\n",
584
     function,
585
     file_name_values->name_space,
586
     libfsntfs_debug_print_file_name_attribute_name_space(
587
      file_name_values->name_space ) );
588
  }
589
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
590
591
6.54k
  data_offset = sizeof( fsntfs_file_name_t );
592
593
6.54k
  if( name_size > 0 )
594
6.53k
  {
595
6.53k
    name_size *= 2;
596
597
6.53k
    if( (size_t) name_size > ( data_size - data_offset ) )
598
36
    {
599
36
      libcerror_error_set(
600
36
       error,
601
36
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
602
36
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
603
36
       "%s: invalid name size value out of bounds.",
604
36
       function );
605
606
36
      goto on_error;
607
36
    }
608
6.50k
    if( libfsntfs_file_name_values_set_name(
609
6.50k
         file_name_values,
610
6.50k
         &( data[ data_offset ] ),
611
6.50k
         (size_t) name_size,
612
6.50k
         error ) != 1 )
613
0
    {
614
0
      libcerror_error_set(
615
0
       error,
616
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
617
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
618
0
       "%s: unable to set name.",
619
0
       function );
620
621
0
      goto on_error;
622
0
    }
623
#if defined( HAVE_DEBUG_OUTPUT )
624
    if( libcnotify_verbose != 0 )
625
    {
626
      if( libfsntfs_debug_print_utf16_string_value(
627
           function,
628
           "name\t\t\t\t",
629
           file_name_values->name,
630
           file_name_values->name_size,
631
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
632
           error ) != 1 )
633
      {
634
        libcerror_error_set(
635
         error,
636
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
637
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
638
         "%s: unable to print UTF-16 string value.",
639
         function );
640
641
        goto on_error;
642
      }
643
      libcnotify_printf(
644
       "\n" );
645
    }
646
    data_offset += file_name_values->name_size;
647
648
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
649
650
/* TODO debug print alignment padding */
651
6.50k
  }
652
#if defined( HAVE_DEBUG_OUTPUT )
653
  if( libcnotify_verbose != 0 )
654
  {
655
    if( data_offset < data_size )
656
    {
657
      libcnotify_printf(
658
       "%s: trailing data:\n",
659
       function );
660
      libcnotify_print_data(
661
       &( data[ data_offset ] ),
662
       data_size - data_offset,
663
       0 );
664
    }
665
  }
666
#endif
667
6.50k
  return( 1 );
668
669
36
on_error:
670
36
  if( file_name_values->name != NULL )
671
0
  {
672
0
    memory_free(
673
0
     file_name_values->name );
674
675
0
    file_name_values->name = NULL;
676
0
  }
677
36
  file_name_values->name_size = 0;
678
679
36
  return( -1 );
680
6.54k
}
681
682
/* Reads the file name values from an MFT attribute
683
 * Returns 1 if successful or -1 on error
684
 */
685
int libfsntfs_file_name_values_read_from_mft_attribute(
686
     libfsntfs_file_name_values_t *file_name_values,
687
     libfsntfs_mft_attribute_t *mft_attribute,
688
     libcerror_error_t **error )
689
2.88k
{
690
2.88k
  uint8_t *data           = NULL;
691
2.88k
  static char *function   = "libfsntfs_file_name_values_read_from_mft_attribute";
692
2.88k
  size_t data_size        = 0;
693
2.88k
  uint32_t attribute_type = 0;
694
2.88k
  int result              = 0;
695
696
2.88k
  if( file_name_values == NULL )
697
0
  {
698
0
    libcerror_error_set(
699
0
     error,
700
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
701
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
702
0
     "%s: invalid file name values.",
703
0
     function );
704
705
0
    return( -1 );
706
0
  }
707
2.88k
  if( libfsntfs_mft_attribute_get_type(
708
2.88k
       mft_attribute,
709
2.88k
       &attribute_type,
710
2.88k
       error ) != 1 )
711
0
  {
712
0
    libcerror_error_set(
713
0
     error,
714
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
715
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
716
0
     "%s: unable to retrieve type from attribute.",
717
0
     function );
718
719
0
    return( -1 );
720
0
  }
721
2.88k
  if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_FILE_NAME )
722
0
  {
723
0
    libcerror_error_set(
724
0
     error,
725
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
726
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
727
0
     "%s: unsupported attribute type.",
728
0
     function );
729
730
0
    return( -1 );
731
0
  }
732
2.88k
  result = libfsntfs_mft_attribute_data_is_resident(
733
2.88k
            mft_attribute,
734
2.88k
            error );
735
736
2.88k
  if( result == -1 )
737
0
  {
738
0
    libcerror_error_set(
739
0
     error,
740
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
741
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
742
0
     "%s: unable to determine if attribute data is resident.",
743
0
     function );
744
745
0
    return( -1 );
746
0
  }
747
2.88k
  else if( result == 0 )
748
12
  {
749
12
    libcerror_error_set(
750
12
     error,
751
12
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
752
12
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
753
12
     "%s: unsupported non-resident attribute.",
754
12
     function );
755
756
12
    return( 1 );
757
12
  }
758
2.86k
  if( libfsntfs_mft_attribute_get_resident_data(
759
2.86k
       mft_attribute,
760
2.86k
       &data,
761
2.86k
       &data_size,
762
2.86k
       error ) != 1 )
763
0
  {
764
0
    libcerror_error_set(
765
0
     error,
766
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
767
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
768
0
     "%s: unable to retrieve resident data from attribute.",
769
0
     function );
770
771
0
    return( -1 );
772
0
  }
773
2.86k
  if( libfsntfs_file_name_values_read_data(
774
2.86k
       file_name_values,
775
2.86k
       data,
776
2.86k
       data_size,
777
2.86k
       error ) != 1 )
778
50
  {
779
50
    libcerror_error_set(
780
50
     error,
781
50
     LIBCERROR_ERROR_DOMAIN_IO,
782
50
     LIBCERROR_IO_ERROR_READ_FAILED,
783
50
     "%s: unable to read file name values.",
784
50
     function );
785
786
50
    return( -1 );
787
50
  }
788
2.81k
  return( 1 );
789
2.86k
}
790
791
/* Retrieves the parent file reference
792
 * Returns 1 if successful or -1 on error
793
 */
794
int libfsntfs_file_name_values_get_parent_file_reference(
795
     libfsntfs_file_name_values_t *file_name_values,
796
     uint64_t *parent_file_reference,
797
     libcerror_error_t **error )
798
0
{
799
0
  static char *function = "libfsntfs_file_name_values_get_parent_file_reference";
800
801
0
  if( file_name_values == NULL )
802
0
  {
803
0
    libcerror_error_set(
804
0
     error,
805
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
806
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
807
0
     "%s: invalid file name values.",
808
0
     function );
809
810
0
    return( -1 );
811
0
  }
812
0
  if( parent_file_reference == NULL )
813
0
  {
814
0
    libcerror_error_set(
815
0
     error,
816
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
817
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
818
0
     "%s: invalid parent file reference.",
819
0
     function );
820
821
0
    return( -1 );
822
0
  }
823
0
  *parent_file_reference = file_name_values->parent_file_reference;
824
825
0
  return( 1 );
826
0
}
827
828
/* Retrieves the creation date and time
829
 * Returns 1 if successful or -1 on error
830
 */
831
int libfsntfs_file_name_values_get_creation_time(
832
     libfsntfs_file_name_values_t *file_name_values,
833
     uint64_t *filetime,
834
     libcerror_error_t **error )
835
0
{
836
0
  static char *function = "libfsntfs_file_name_values_get_creation_time";
837
838
0
  if( file_name_values == NULL )
839
0
  {
840
0
    libcerror_error_set(
841
0
     error,
842
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
843
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
844
0
     "%s: invalid file name values.",
845
0
     function );
846
847
0
    return( -1 );
848
0
  }
849
0
  if( filetime == NULL )
850
0
  {
851
0
    libcerror_error_set(
852
0
     error,
853
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
854
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
855
0
     "%s: invalid FILETIME.",
856
0
     function );
857
858
0
    return( -1 );
859
0
  }
860
0
  *filetime = file_name_values->creation_time;
861
862
0
  return( 1 );
863
0
}
864
865
/* Retrieves the (file) modification (last written) date and time
866
 * Returns 1 if successful or -1 on error
867
 */
868
int libfsntfs_file_name_values_get_modification_time(
869
     libfsntfs_file_name_values_t *file_name_values,
870
     uint64_t *filetime,
871
     libcerror_error_t **error )
872
0
{
873
0
  static char *function = "libfsntfs_file_name_values_get_modification_time";
874
875
0
  if( file_name_values == NULL )
876
0
  {
877
0
    libcerror_error_set(
878
0
     error,
879
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
880
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
881
0
     "%s: invalid file name values.",
882
0
     function );
883
884
0
    return( -1 );
885
0
  }
886
0
  if( filetime == 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 FILETIME.",
893
0
     function );
894
895
0
    return( -1 );
896
0
  }
897
0
  *filetime = file_name_values->modification_time;
898
899
0
  return( 1 );
900
0
}
901
902
/* Retrieves the access date and time
903
 * Returns 1 if successful or -1 on error
904
 */
905
int libfsntfs_file_name_values_get_access_time(
906
     libfsntfs_file_name_values_t *file_name_values,
907
     uint64_t *filetime,
908
     libcerror_error_t **error )
909
0
{
910
0
  static char *function = "libfsntfs_file_name_values_get_access_time";
911
912
0
  if( file_name_values == NULL )
913
0
  {
914
0
    libcerror_error_set(
915
0
     error,
916
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
917
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
918
0
     "%s: invalid file name values.",
919
0
     function );
920
921
0
    return( -1 );
922
0
  }
923
0
  if( filetime == NULL )
924
0
  {
925
0
    libcerror_error_set(
926
0
     error,
927
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
928
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
929
0
     "%s: invalid FILETIME.",
930
0
     function );
931
932
0
    return( -1 );
933
0
  }
934
0
  *filetime = file_name_values->access_time;
935
936
0
  return( 1 );
937
0
}
938
939
/* Retrieves the (file system entry) modification date and time
940
 * Returns 1 if successful or -1 on error
941
 */
942
int libfsntfs_file_name_values_get_entry_modification_time(
943
     libfsntfs_file_name_values_t *file_name_values,
944
     uint64_t *filetime,
945
     libcerror_error_t **error )
946
0
{
947
0
  static char *function = "libfsntfs_file_name_values_get_entry_modification_time";
948
949
0
  if( file_name_values == NULL )
950
0
  {
951
0
    libcerror_error_set(
952
0
     error,
953
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
954
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
955
0
     "%s: invalid file name values.",
956
0
     function );
957
958
0
    return( -1 );
959
0
  }
960
0
  if( filetime == NULL )
961
0
  {
962
0
    libcerror_error_set(
963
0
     error,
964
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
965
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
966
0
     "%s: invalid FILETIME.",
967
0
     function );
968
969
0
    return( -1 );
970
0
  }
971
0
  *filetime = file_name_values->entry_modification_time;
972
973
0
  return( 1 );
974
0
}
975
976
/* Retrieves the file attribute flags
977
 * Returns 1 if successful or -1 on error
978
 */
979
int libfsntfs_file_name_values_get_file_attribute_flags(
980
     libfsntfs_file_name_values_t *file_name_values,
981
     uint32_t *file_attribute_flags,
982
     libcerror_error_t **error )
983
0
{
984
0
  static char *function = "libfsntfs_file_name_values_get_file_attribute_flags";
985
986
0
  if( file_name_values == NULL )
987
0
  {
988
0
    libcerror_error_set(
989
0
     error,
990
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
991
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
992
0
     "%s: invalid file name values.",
993
0
     function );
994
995
0
    return( -1 );
996
0
  }
997
0
  if( file_attribute_flags == NULL )
998
0
  {
999
0
    libcerror_error_set(
1000
0
     error,
1001
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1002
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1003
0
     "%s: invalid file attribute flags.",
1004
0
     function );
1005
1006
0
    return( -1 );
1007
0
  }
1008
0
  *file_attribute_flags = file_name_values->file_attribute_flags;
1009
1010
0
  return( 1 );
1011
0
}
1012
1013
/* Retrieves the name space
1014
 * Returns 1 if successful or -1 on error
1015
 */
1016
int libfsntfs_file_name_values_get_name_space(
1017
     libfsntfs_file_name_values_t *file_name_values,
1018
     uint8_t *name_space,
1019
     libcerror_error_t **error )
1020
0
{
1021
0
  static char *function = "libfsntfs_file_name_values_get_name_space";
1022
1023
0
  if( file_name_values == NULL )
1024
0
  {
1025
0
    libcerror_error_set(
1026
0
     error,
1027
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1028
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1029
0
     "%s: invalid file name values.",
1030
0
     function );
1031
1032
0
    return( -1 );
1033
0
  }
1034
0
  if( name_space == NULL )
1035
0
  {
1036
0
    libcerror_error_set(
1037
0
     error,
1038
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1039
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1040
0
     "%s: invalid name space.",
1041
0
     function );
1042
1043
0
    return( -1 );
1044
0
  }
1045
0
  *name_space = file_name_values->name_space;
1046
1047
0
  return( 1 );
1048
0
}
1049
1050
/* Retrieves the size of the UTF-8 encoded name
1051
 * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode
1052
 * The returned size includes the end of string character
1053
 * Returns 1 if successful or -1 on error
1054
 */
1055
int libfsntfs_file_name_values_get_utf8_name_size(
1056
     libfsntfs_file_name_values_t *file_name_values,
1057
     size_t *utf8_string_size,
1058
     libcerror_error_t **error )
1059
0
{
1060
0
  static char *function = "libfsntfs_file_name_values_get_utf8_name_size";
1061
1062
0
  if( file_name_values == NULL )
1063
0
  {
1064
0
    libcerror_error_set(
1065
0
     error,
1066
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1067
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1068
0
     "%s: invalid file name values.",
1069
0
     function );
1070
1071
0
    return( -1 );
1072
0
  }
1073
0
  if( libuna_utf8_string_size_from_utf16_stream(
1074
0
       file_name_values->name,
1075
0
       (size_t) file_name_values->name_size,
1076
0
       LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
1077
0
       utf8_string_size,
1078
0
       error ) != 1 )
1079
0
  {
1080
0
    libcerror_error_set(
1081
0
     error,
1082
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1083
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1084
0
     "%s: unable to retrieve UTF-8 string size.",
1085
0
     function );
1086
1087
0
    return( -1 );
1088
0
  }
1089
0
  return( 1 );
1090
0
}
1091
1092
/* Retrieves the UTF-8 encoded name
1093
 * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode
1094
 * The size should include the end of string character
1095
 * Returns 1 if successful or -1 on error
1096
 */
1097
int libfsntfs_file_name_values_get_utf8_name(
1098
     libfsntfs_file_name_values_t *file_name_values,
1099
     uint8_t *utf8_string,
1100
     size_t utf8_string_size,
1101
     libcerror_error_t **error )
1102
0
{
1103
0
  static char *function = "libfsntfs_file_name_values_get_utf8_name";
1104
1105
0
  if( file_name_values == NULL )
1106
0
  {
1107
0
    libcerror_error_set(
1108
0
     error,
1109
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1110
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1111
0
     "%s: invalid file name values.",
1112
0
     function );
1113
1114
0
    return( -1 );
1115
0
  }
1116
0
  if( libuna_utf8_string_copy_from_utf16_stream(
1117
0
       utf8_string,
1118
0
       utf8_string_size,
1119
0
       file_name_values->name,
1120
0
       (size_t) file_name_values->name_size,
1121
0
       LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
1122
0
       error ) != 1 )
1123
0
  {
1124
0
    libcerror_error_set(
1125
0
     error,
1126
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1127
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1128
0
     "%s: unable to retrieve UTF-8 string.",
1129
0
     function );
1130
1131
0
    return( -1 );
1132
0
  }
1133
#if defined( HAVE_DEBUG_OUTPUT )
1134
  if( libcnotify_verbose != 0 )
1135
  {
1136
    libcnotify_printf(
1137
     "%s: string data:\n",
1138
     function );
1139
    libcnotify_print_data(
1140
     utf8_string,
1141
     utf8_string_size,
1142
     0 );
1143
  }
1144
#endif
1145
0
  return( 1 );
1146
0
}
1147
1148
/* Retrieves the size of the UTF-16 encoded name
1149
 * This function uses UCS-2 (with surrogates) to support characters outside Unicode
1150
 * The returned size includes the end of string character
1151
 * Returns 1 if successful or -1 on error
1152
 */
1153
int libfsntfs_file_name_values_get_utf16_name_size(
1154
     libfsntfs_file_name_values_t *file_name_values,
1155
     size_t *utf16_string_size,
1156
     libcerror_error_t **error )
1157
0
{
1158
0
  static char *function = "libfsntfs_file_name_values_get_utf16_name_size";
1159
1160
0
  if( file_name_values == NULL )
1161
0
  {
1162
0
    libcerror_error_set(
1163
0
     error,
1164
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1165
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1166
0
     "%s: invalid file name values.",
1167
0
     function );
1168
1169
0
    return( -1 );
1170
0
  }
1171
0
  if( libuna_utf16_string_size_from_utf16_stream(
1172
0
       file_name_values->name,
1173
0
       (size_t) file_name_values->name_size,
1174
0
       LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
1175
0
       utf16_string_size,
1176
0
       error ) != 1 )
1177
0
  {
1178
0
    libcerror_error_set(
1179
0
     error,
1180
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1181
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1182
0
     "%s: unable to retrieve UTF-16 string size.",
1183
0
     function );
1184
1185
0
    return( -1 );
1186
0
  }
1187
0
  return( 1 );
1188
0
}
1189
1190
/* Retrieves the UTF-16 encoded name
1191
 * This function uses UCS-2 (with surrogates) to support characters outside Unicode
1192
 * The size should include the end of string character
1193
 * Returns 1 if successful or -1 on error
1194
 */
1195
int libfsntfs_file_name_values_get_utf16_name(
1196
     libfsntfs_file_name_values_t *file_name_values,
1197
     uint16_t *utf16_string,
1198
     size_t utf16_string_size,
1199
     libcerror_error_t **error )
1200
0
{
1201
0
  static char *function = "libfsntfs_file_name_values_get_utf16_name";
1202
1203
0
  if( file_name_values == NULL )
1204
0
  {
1205
0
    libcerror_error_set(
1206
0
     error,
1207
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1208
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1209
0
     "%s: invalid file name values.",
1210
0
     function );
1211
1212
0
    return( -1 );
1213
0
  }
1214
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1215
0
       utf16_string,
1216
0
       utf16_string_size,
1217
0
       file_name_values->name,
1218
0
       (size_t) file_name_values->name_size,
1219
0
       LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
1220
0
       error ) != 1 )
1221
0
  {
1222
0
    libcerror_error_set(
1223
0
     error,
1224
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1225
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1226
0
     "%s: unable to retrieve UTF-16 string.",
1227
0
     function );
1228
1229
0
    return( -1 );
1230
0
  }
1231
0
  return( 1 );
1232
0
}
1233