Coverage Report

Created: 2025-09-05 06:58

/src/libfsntfs/libfsntfs/libfsntfs_name.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Name 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 <types.h>
24
25
#if defined( HAVE_WCTYPE_H )
26
#include <wctype.h>
27
#endif
28
29
#include "libfsntfs_libcerror.h"
30
#include "libfsntfs_libuna.h"
31
#include "libfsntfs_name.h"
32
33
/* Compares an (other) UTF-16 encoded name with an UTF-16 encoded name
34
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
35
 */
36
int libfsntfs_name_compare(
37
     const uint8_t *name,
38
     size_t name_size,
39
     const uint8_t *other_name,
40
     size_t other_name_size,
41
     uint8_t use_case_folding,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function                           = "libfsntfs_name_compare";
45
0
  libuna_unicode_character_t name_character       = 0;
46
0
  libuna_unicode_character_t other_name_character = 0;
47
0
  size_t name_index                               = 0;
48
0
  size_t other_name_index                         = 0;
49
50
0
  if( name == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid UTF-16 encoded name.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
0
  if( name_size > (size_t) SSIZE_MAX )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
67
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
0
  if( name_size == 0 )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
78
0
     "%s: missing UTF-16 encoded name value.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
0
  if( other_name == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
88
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
89
0
     "%s: invalid UTF-16 encoded other name.",
90
0
     function );
91
92
0
    return( -1 );
93
0
  }
94
0
  if( other_name_size > (size_t) SSIZE_MAX )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
99
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
100
0
     "%s: invalid UTF-16 encoded other name size value exceeds maximum.",
101
0
     function );
102
103
0
    return( -1 );
104
0
  }
105
0
  if( other_name_size == 0 )
106
0
  {
107
0
    libcerror_error_set(
108
0
     error,
109
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
110
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
111
0
     "%s: missing UTF-16 encoded other name value.",
112
0
     function );
113
114
0
    return( -1 );
115
0
  }
116
  /* Check if the UTF-16 streams are terminated with zero bytes
117
   */
118
0
  if( ( name_size >= 2 )
119
0
   && ( name[ name_size - 2 ] == 0 )
120
0
   && ( name[ name_size - 1 ] == 0 ) )
121
0
  {
122
0
    name_size -= 2;
123
0
  }
124
0
  if( ( other_name_size >= 2 )
125
0
   && ( other_name[ other_name_size - 2 ] == 0 )
126
0
   && ( other_name[ other_name_size - 1 ] == 0 ) )
127
0
  {
128
0
    other_name_size -= 2;
129
0
  }
130
0
  while( ( name_index < name_size )
131
0
      && ( other_name_index < other_name_size ) )
132
0
  {
133
0
    if( libuna_unicode_character_copy_from_utf16_stream(
134
0
         &name_character,
135
0
         name,
136
0
         name_size,
137
0
         &name_index,
138
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
139
0
         error ) != 1 )
140
0
    {
141
0
      libcerror_error_set(
142
0
       error,
143
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
144
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
145
0
       "%s: unable to copy UTF-16 encoded name to Unicode character.",
146
0
       function );
147
148
0
      return( -1 );
149
0
    }
150
0
    if( libuna_unicode_character_copy_from_utf16_stream(
151
0
         &other_name_character,
152
0
         other_name,
153
0
         other_name_size,
154
0
         &other_name_index,
155
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
156
0
         error ) != 1 )
157
0
    {
158
0
      libcerror_error_set(
159
0
       error,
160
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
161
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
162
0
       "%s: unable to copy UTF-16 encoded other name to Unicode character.",
163
0
       function );
164
165
0
      return( -1 );
166
0
    }
167
0
    if( use_case_folding != 0 )
168
0
    {
169
0
      name_character       = (libuna_unicode_character_t) towupper( (wint_t) name_character );
170
0
      other_name_character = (libuna_unicode_character_t) towupper( (wint_t) other_name_character );
171
0
    }
172
0
    if( other_name_character < name_character )
173
0
    {
174
0
      return( LIBUNA_COMPARE_LESS );
175
0
    }
176
0
    else if( other_name_character > name_character )
177
0
    {
178
0
      return( LIBUNA_COMPARE_GREATER );
179
0
    }
180
0
  }
181
0
  if( other_name_index < other_name_size )
182
0
  {
183
0
    return( LIBUNA_COMPARE_GREATER );
184
0
  }
185
0
  else if( name_index < name_size )
186
0
  {
187
0
    return( LIBUNA_COMPARE_LESS );
188
0
  }
189
0
  return( LIBUNA_COMPARE_EQUAL );
190
0
}
191
192
/* Compares an UTF-16 encoded short name with an UTF-16 encoded (long) name
193
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
194
 */
195
int libfsntfs_name_compare_short(
196
     const uint8_t *name,
197
     size_t name_size,
198
     const uint8_t *short_name,
199
     size_t short_name_size,
200
     libcerror_error_t **error )
201
0
{
202
0
  static char *function                           = "libfsntfs_name_compare_short";
203
0
  libuna_unicode_character_t name_character       = 0;
204
0
  libuna_unicode_character_t short_name_character = 0;
205
0
  size_t last_match_name_index                    = 0;
206
0
  size_t last_match_short_name_index              = 0;
207
0
  size_t name_index                               = 0;
208
0
  size_t short_name_index                         = 0;
209
210
0
  if( name == NULL )
211
0
  {
212
0
    libcerror_error_set(
213
0
     error,
214
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
215
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
216
0
     "%s: invalid UTF-16 encoded name.",
217
0
     function );
218
219
0
    return( -1 );
220
0
  }
221
0
  if( name_size > (size_t) SSIZE_MAX )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
226
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
227
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
228
0
     function );
229
230
0
    return( -1 );
231
0
  }
232
0
  if( name_size == 0 )
233
0
  {
234
0
    libcerror_error_set(
235
0
     error,
236
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
237
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
238
0
     "%s: missing UTF-16 encoded name value.",
239
0
     function );
240
241
0
    return( -1 );
242
0
  }
243
0
  if( short_name == NULL )
244
0
  {
245
0
    libcerror_error_set(
246
0
     error,
247
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
248
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
249
0
     "%s: invalid UTF-16 encoded short name.",
250
0
     function );
251
252
0
    return( -1 );
253
0
  }
254
0
  if( short_name_size > (size_t) SSIZE_MAX )
255
0
  {
256
0
    libcerror_error_set(
257
0
     error,
258
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
259
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
260
0
     "%s: invalid UTF-16 encoded short name size value exceeds maximum.",
261
0
     function );
262
263
0
    return( -1 );
264
0
  }
265
0
  if( short_name_size == 0 )
266
0
  {
267
0
    libcerror_error_set(
268
0
     error,
269
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
270
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
271
0
     "%s: missing UTF-16 encoded short name value.",
272
0
     function );
273
274
0
    return( -1 );
275
0
  }
276
  /* Check if the UTF-16 streams are terminated with zero bytes
277
   */
278
0
  if( ( name_size >= 2 )
279
0
   && ( name[ name_size - 2 ] == 0 )
280
0
   && ( name[ name_size - 1 ] == 0 ) )
281
0
  {
282
0
    name_size -= 2;
283
0
  }
284
0
  if( ( short_name_size >= 2 )
285
0
   && ( short_name[ short_name_size - 2 ] == 0 )
286
0
   && ( short_name[ short_name_size - 1 ] == 0 ) )
287
0
  {
288
0
    short_name_size -= 2;
289
0
  }
290
0
  while( ( name_index < name_size )
291
0
      && ( short_name_index < short_name_size ) )
292
0
  {
293
0
    if( libuna_unicode_character_copy_from_utf16_stream(
294
0
         &name_character,
295
0
         name,
296
0
         name_size,
297
0
         &name_index,
298
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
299
0
         error ) != 1 )
300
0
    {
301
0
      libcerror_error_set(
302
0
       error,
303
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
304
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
305
0
       "%s: unable to copy UTF-16 encoded name to Unicode character.",
306
0
       function );
307
308
0
      return( -1 );
309
0
    }
310
    /* Ignore:
311
     * control characters and space
312
     * '"' '*' '+' ',' '.' '/' ':' ';' '<' '=' '>' '?' '\'
313
     * non 7-bit ASCII characters
314
     */
315
0
    if( ( name_character <= 0x20 )
316
0
     || ( name_character == 0x22 )
317
0
     || ( ( name_character >= 0x2a )
318
0
      &&  ( name_character <= 0x2c ) )
319
0
     || ( name_character == 0x2e )
320
0
     || ( name_character == 0x2f )
321
0
     || ( ( name_character >= 0x3a )
322
0
      &&  ( name_character <= 0x3f ) )
323
0
     || ( name_character == 0x5c )
324
0
     || ( name_character >= 0x80 ) )
325
0
    {
326
0
      continue;
327
0
    }
328
    /* The [ and ] characters are replaced by an underscore (_)
329
     */
330
0
    if( ( name_character == 0x5b )
331
0
     || ( name_character == 0x5d ) )
332
0
    {
333
0
      name_character = 0x5f;
334
0
    }
335
0
    if( libuna_unicode_character_copy_from_utf16_stream(
336
0
         &short_name_character,
337
0
         short_name,
338
0
         short_name_size,
339
0
         &short_name_index,
340
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
341
0
         error ) != 1 )
342
0
    {
343
0
      libcerror_error_set(
344
0
       error,
345
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
346
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
347
0
       "%s: unable to copy UTF-16 encoded short name to Unicode character.",
348
0
       function );
349
350
0
      return( -1 );
351
0
    }
352
0
    if( short_name_character == 0x7e )
353
0
    {
354
0
      break;
355
0
    }
356
0
    name_character       = (libuna_unicode_character_t) towupper( (wint_t) name_character );
357
0
    short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character );
358
359
0
    if( last_match_short_name_index < 4 )
360
0
    {
361
0
      if( short_name_character < name_character )
362
0
      {
363
0
        return( LIBUNA_COMPARE_LESS );
364
0
      }
365
0
      else if( short_name_character > name_character )
366
0
      {
367
0
        return( LIBUNA_COMPARE_GREATER );
368
0
      }
369
0
    }
370
0
    else if( short_name_character != name_character )
371
0
    {
372
/* TODO handle hex notation */
373
0
      break;
374
0
    }
375
0
    last_match_name_index       = name_index;
376
0
    last_match_short_name_index = short_name_index;
377
0
  }
378
0
  while( ( short_name_index < short_name_size )
379
0
      && ( short_name_character != 0x7e ) )
380
0
  {
381
0
    if( libuna_unicode_character_copy_from_utf16_stream(
382
0
         &short_name_character,
383
0
         short_name,
384
0
         short_name_size,
385
0
         &short_name_index,
386
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
387
0
         error ) != 1 )
388
0
    {
389
0
      libcerror_error_set(
390
0
       error,
391
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
392
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
393
0
       "%s: unable to copy UTF-16 encoded short name to Unicode character.",
394
0
       function );
395
396
0
      return( -1 );
397
0
    }
398
0
  }
399
0
  if( short_name_character != 0x7e )
400
0
  {
401
0
    libcerror_error_set(
402
0
     error,
403
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
404
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
405
0
     "%s: invalid short name - missing tilde character\n",
406
0
     function );
407
408
0
    return( -1 );
409
0
  }
410
0
  while( short_name_index < short_name_size )
411
0
  {
412
0
    if( libuna_unicode_character_copy_from_utf16_stream(
413
0
         &short_name_character,
414
0
         short_name,
415
0
         short_name_size,
416
0
         &short_name_index,
417
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
418
0
         error ) != 1 )
419
0
    {
420
0
      libcerror_error_set(
421
0
       error,
422
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
423
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
424
0
       "%s: unable to copy UTF-16 encoded short name to Unicode character.",
425
0
       function );
426
427
0
      return( -1 );
428
0
    }
429
0
    if( short_name_character == 0x2e )
430
0
    {
431
0
      break;
432
0
    }
433
    /* The ~ suffix should only consist of the numeric characters 0 - 9
434
     */
435
0
    if( ( short_name_character < 0x30 )
436
0
     || ( short_name_character > 0x39 ) )
437
0
    {
438
0
      libcerror_error_set(
439
0
       error,
440
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
441
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
442
0
       "%s: invalid short name - non-numeric character in tilde suffix.",
443
0
       function );
444
445
0
      return( -1 );
446
0
    }
447
0
  }
448
0
  if( short_name_character == 0x2e )
449
0
  {
450
0
    name_index = name_size;
451
452
0
    while( name_index >= 2 )
453
0
    {
454
0
      name_index -= 2;
455
456
0
      if( libuna_unicode_character_copy_from_utf16_stream(
457
0
           &name_character,
458
0
           name,
459
0
           name_size,
460
0
           &name_index,
461
0
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
462
0
           error ) != 1 )
463
0
      {
464
0
        libcerror_error_set(
465
0
         error,
466
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
467
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
468
0
         "%s: unable to copy UTF-16 encoded name to Unicode character.",
469
0
         function );
470
471
0
        return( -1 );
472
0
      }
473
0
      if( name_character == 0x2e )
474
0
      {
475
0
        break;
476
0
      }
477
0
      name_index -= 2;
478
0
    }
479
0
  }
480
0
  if( name_character == 0x2e )
481
0
  {
482
0
    while( ( name_index < name_size )
483
0
        && ( short_name_index < short_name_size ) )
484
0
    {
485
0
      if( libuna_unicode_character_copy_from_utf16_stream(
486
0
           &name_character,
487
0
           name,
488
0
           name_size,
489
0
           &name_index,
490
0
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
491
0
           error ) != 1 )
492
0
      {
493
0
        libcerror_error_set(
494
0
         error,
495
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
496
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
497
0
         "%s: unable to copy UTF-16 encoded name to Unicode character.",
498
0
         function );
499
500
0
        return( -1 );
501
0
      }
502
      /* Ignore:
503
       * control characters and space
504
       * '"' '*' '+' ',' '/' ':' ';' '<' '=' '>' '?' '\'
505
       * non 7-bit ASCII characters
506
       */
507
0
      if( ( name_character <= 0x20 )
508
0
       || ( name_character == 0x22 )
509
0
       || ( ( name_character >= 0x2a )
510
0
        &&  ( name_character <= 0x2c ) )
511
0
       || ( name_character == 0x2f )
512
0
       || ( ( name_character >= 0x3a )
513
0
        &&  ( name_character <= 0x3f ) )
514
0
       || ( name_character == 0x5c )
515
0
       || ( name_character >= 0x80 ) )
516
0
      {
517
0
        continue;
518
0
      }
519
0
      if( libuna_unicode_character_copy_from_utf16_stream(
520
0
           &short_name_character,
521
0
           short_name,
522
0
           short_name_size,
523
0
           &short_name_index,
524
0
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
525
0
           error ) != 1 )
526
0
      {
527
0
        libcerror_error_set(
528
0
         error,
529
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
530
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
531
0
         "%s: unable to copy UTF-16 encoded short name to Unicode character.",
532
0
         function );
533
534
0
        return( -1 );
535
0
      }
536
0
      name_character       = (libuna_unicode_character_t) towupper( (wint_t) name_character );
537
0
      short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character );
538
539
0
      if( short_name_character != name_character )
540
0
      {
541
0
        break;
542
0
      }
543
0
    }
544
0
  }
545
0
  if( short_name_index < short_name_size )
546
0
  {
547
0
    name_index       = last_match_name_index;
548
0
    short_name_index = last_match_short_name_index;
549
550
    /* The name was shorter than the short name
551
     */
552
0
    if( name_index >= name_size )
553
0
    {
554
0
      return( LIBUNA_COMPARE_GREATER );
555
0
    }
556
    /* Compare the remainder of the name and short name as a case-insenstive string
557
     */
558
0
    while( ( name_index < name_size )
559
0
        && ( short_name_index < short_name_size ) )
560
0
    {
561
0
      if( libuna_unicode_character_copy_from_utf16_stream(
562
0
           &name_character,
563
0
           name,
564
0
           name_size,
565
0
           &name_index,
566
0
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
567
0
           error ) != 1 )
568
0
      {
569
0
        libcerror_error_set(
570
0
         error,
571
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
572
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
573
0
         "%s: unable to copy UTF-16 encoded name to Unicode character.",
574
0
         function );
575
576
0
        return( -1 );
577
0
      }
578
0
      if( libuna_unicode_character_copy_from_utf16_stream(
579
0
           &short_name_character,
580
0
           short_name,
581
0
           short_name_size,
582
0
           &short_name_index,
583
0
           LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
584
0
           error ) != 1 )
585
0
      {
586
0
        libcerror_error_set(
587
0
         error,
588
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
589
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
590
0
         "%s: unable to copy UTF-16 encoded short name to Unicode character.",
591
0
         function );
592
593
0
        return( -1 );
594
0
      }
595
0
      name_character       = (libuna_unicode_character_t) towupper( (wint_t) name_character );
596
0
      short_name_character = (libuna_unicode_character_t) towupper( (wint_t) short_name_character );
597
598
0
      if( short_name_character < name_character )
599
0
      {
600
0
        return( LIBUNA_COMPARE_LESS );
601
0
      }
602
0
      else if( short_name_character > name_character )
603
0
      {
604
0
        return( LIBUNA_COMPARE_GREATER );
605
0
      }
606
0
    }
607
0
  }
608
0
  return( LIBUNA_COMPARE_EQUAL );
609
0
}
610
611
/* Compares an UTF-8 string with an UTF-16 encoded name
612
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
613
 */
614
int libfsntfs_name_compare_with_utf8_string(
615
     const uint8_t *name,
616
     size_t name_size,
617
     const libuna_utf8_character_t *utf8_string,
618
     size_t utf8_string_length,
619
     uint8_t use_case_folding,
620
     libcerror_error_t **error )
621
39.2k
{
622
39.2k
  static char *function                       = "libfsntfs_name_compare_with_utf8_string";
623
39.2k
  libuna_unicode_character_t name_character   = 0;
624
39.2k
  libuna_unicode_character_t string_character = 0;
625
39.2k
  size_t name_index                           = 0;
626
39.2k
  size_t utf8_string_index                    = 0;
627
628
39.2k
  if( name == NULL )
629
13
  {
630
13
    libcerror_error_set(
631
13
     error,
632
13
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
633
13
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
634
13
     "%s: invalid UTF-16 encoded name.",
635
13
     function );
636
637
13
    return( -1 );
638
13
  }
639
39.2k
  if( name_size > (size_t) SSIZE_MAX )
640
0
  {
641
0
    libcerror_error_set(
642
0
     error,
643
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
644
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
645
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
646
0
     function );
647
648
0
    return( -1 );
649
0
  }
650
39.2k
  if( name_size == 0 )
651
0
  {
652
0
    libcerror_error_set(
653
0
     error,
654
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
655
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
656
0
     "%s: missing UTF-16 encoded name value.",
657
0
     function );
658
659
0
    return( -1 );
660
0
  }
661
39.2k
  if( utf8_string == NULL )
662
0
  {
663
0
    libcerror_error_set(
664
0
     error,
665
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
666
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
667
0
     "%s: invalid UTF-8 string.",
668
0
     function );
669
670
0
    return( -1 );
671
0
  }
672
39.2k
  if( utf8_string_length > (size_t) SSIZE_MAX )
673
0
  {
674
0
    libcerror_error_set(
675
0
     error,
676
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
677
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
678
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
679
0
     function );
680
681
0
    return( -1 );
682
0
  }
683
  /* Check if the UTF-16 stream is terminated with zero bytes
684
   */
685
39.2k
  if( ( name_size >= 2 )
686
39.2k
   && ( name[ name_size - 2 ] == 0 )
687
39.2k
   && ( name[ name_size - 1 ] == 0 ) )
688
8.65k
  {
689
8.65k
    name_size -= 2;
690
8.65k
  }
691
39.2k
  if( ( utf8_string_length >= 1 )
692
39.2k
   && ( utf8_string[ utf8_string_length - 1 ] == 0 ) )
693
28.1k
  {
694
28.1k
    utf8_string_length -= 1;
695
28.1k
  }
696
115k
  while( ( name_index < name_size )
697
115k
      && ( utf8_string_index < utf8_string_length ) )
698
103k
  {
699
103k
    if( libuna_unicode_character_copy_from_utf16_stream(
700
103k
         &name_character,
701
103k
         name,
702
103k
         name_size,
703
103k
         &name_index,
704
103k
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
705
103k
         error ) != 1 )
706
0
    {
707
0
      libcerror_error_set(
708
0
       error,
709
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
710
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
711
0
       "%s: unable to copy UTF-16 encoded name to Unicode character.",
712
0
       function );
713
714
0
      return( -1 );
715
0
    }
716
    /* Using RFC 2279 UTF-8 to support unpaired UTF-16 surrogates
717
     */
718
103k
    if( libuna_unicode_character_copy_from_utf8_rfc2279(
719
103k
         &string_character,
720
103k
         utf8_string,
721
103k
         utf8_string_length,
722
103k
         &utf8_string_index,
723
103k
         error ) != 1 )
724
0
    {
725
0
      libcerror_error_set(
726
0
       error,
727
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
728
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
729
0
       "%s: unable to copy UTF-8 RFC 2279 string to Unicode character.",
730
0
       function );
731
732
0
      return( -1 );
733
0
    }
734
103k
    if( use_case_folding != 0 )
735
8.60k
    {
736
8.60k
      name_character   = (libuna_unicode_character_t) towupper( (wint_t) name_character );
737
8.60k
      string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character );
738
8.60k
    }
739
103k
    if( string_character < name_character )
740
14.8k
    {
741
14.8k
      return( LIBUNA_COMPARE_LESS );
742
14.8k
    }
743
88.5k
    else if( string_character > name_character )
744
11.9k
    {
745
11.9k
      return( LIBUNA_COMPARE_GREATER );
746
11.9k
    }
747
103k
  }
748
12.4k
  if( utf8_string_index < utf8_string_length )
749
893
  {
750
893
    return( LIBUNA_COMPARE_GREATER );
751
893
  }
752
11.5k
  else if( name_index < name_size )
753
3.77k
  {
754
3.77k
    return( LIBUNA_COMPARE_LESS );
755
3.77k
  }
756
7.75k
  return( LIBUNA_COMPARE_EQUAL );
757
12.4k
}
758
759
/* Compares an UTF-16 string with an UTF-16 encoded name
760
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
761
 */
762
int libfsntfs_name_compare_with_utf16_string(
763
     const uint8_t *name,
764
     size_t name_size,
765
     const libuna_utf16_character_t *utf16_string,
766
     size_t utf16_string_length,
767
     uint8_t use_case_folding,
768
     libcerror_error_t **error )
769
0
{
770
0
  static char *function                       = "libfsntfs_name_compare_with_utf16_string";
771
0
  libuna_unicode_character_t name_character   = 0;
772
0
  libuna_unicode_character_t string_character = 0;
773
0
  size_t name_index                           = 0;
774
0
  size_t utf16_string_index                   = 0;
775
776
0
  if( name == NULL )
777
0
  {
778
0
    libcerror_error_set(
779
0
     error,
780
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
781
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
782
0
     "%s: invalid UTF-16 encoded name.",
783
0
     function );
784
785
0
    return( -1 );
786
0
  }
787
0
  if( name_size > (size_t) SSIZE_MAX )
788
0
  {
789
0
    libcerror_error_set(
790
0
     error,
791
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
792
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
793
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
794
0
     function );
795
796
0
    return( -1 );
797
0
  }
798
0
  if( name_size == 0 )
799
0
  {
800
0
    libcerror_error_set(
801
0
     error,
802
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
803
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
804
0
     "%s: missing UTF-16 encoded name value.",
805
0
     function );
806
807
0
    return( -1 );
808
0
  }
809
0
  if( utf16_string == NULL )
810
0
  {
811
0
    libcerror_error_set(
812
0
     error,
813
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
814
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
815
0
     "%s: invalid UTF-16 string.",
816
0
     function );
817
818
0
    return( -1 );
819
0
  }
820
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
821
0
  {
822
0
    libcerror_error_set(
823
0
     error,
824
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
825
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
826
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
827
0
     function );
828
829
0
    return( -1 );
830
0
  }
831
  /* Check if the UTF-16 stream is terminated with zero bytes
832
   */
833
0
  if( ( name_size >= 2 )
834
0
   && ( name[ name_size - 2 ] == 0 )
835
0
   && ( name[ name_size - 1 ] == 0 ) )
836
0
  {
837
0
    name_size -= 2;
838
0
  }
839
0
  if( ( utf16_string_length >= 1 )
840
0
   && ( utf16_string[ utf16_string_length - 1 ] == 0 ) )
841
0
  {
842
0
    utf16_string_length -= 1;
843
0
  }
844
0
  while( ( name_index < name_size )
845
0
      && ( utf16_string_index < utf16_string_length ) )
846
0
  {
847
0
    if( libuna_unicode_character_copy_from_utf16_stream(
848
0
         &name_character,
849
0
         name,
850
0
         name_size,
851
0
         &name_index,
852
0
         LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
853
0
         error ) != 1 )
854
0
    {
855
0
      libcerror_error_set(
856
0
       error,
857
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
858
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
859
0
       "%s: unable to copy UTF-16 encoded name to Unicode character.",
860
0
       function );
861
862
0
      return( -1 );
863
0
    }
864
    /* Using UCS-2 to support unpaired UTF-16 surrogates
865
     */
866
0
    if( libuna_unicode_character_copy_from_ucs2(
867
0
         &string_character,
868
0
         utf16_string,
869
0
         utf16_string_length,
870
0
         &utf16_string_index,
871
0
         error ) != 1 )
872
0
    {
873
0
      libcerror_error_set(
874
0
       error,
875
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
876
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
877
0
       "%s: unable to copy UCS-2 string to Unicode character.",
878
0
       function );
879
880
0
      return( -1 );
881
0
    }
882
0
    if( use_case_folding != 0 )
883
0
    {
884
0
      name_character   = (libuna_unicode_character_t) towupper( (wint_t) name_character );
885
0
      string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character );
886
0
    }
887
0
    if( string_character < name_character )
888
0
    {
889
0
      return( LIBUNA_COMPARE_LESS );
890
0
    }
891
0
    else if( string_character > name_character )
892
0
    {
893
0
      return( LIBUNA_COMPARE_GREATER );
894
0
    }
895
0
  }
896
0
  if( utf16_string_index < utf16_string_length )
897
0
  {
898
0
    return( LIBUNA_COMPARE_GREATER );
899
0
  }
900
0
  else if( name_index < name_size )
901
0
  {
902
0
    return( LIBUNA_COMPARE_LESS );
903
0
  }
904
0
  return( LIBUNA_COMPARE_EQUAL );
905
0
}
906