Coverage Report

Created: 2024-02-25 07:20

/src/libfsfat/libfsfat/libfsfat_name.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Name functions
3
 *
4
 * Copyright (C) 2021-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 "libfsfat_libcerror.h"
30
#include "libfsfat_libuna.h"
31
#include "libfsfat_name.h"
32
33
/* Compares an UTF-8 string 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 libfsfat_name_compare_with_utf8_string(
37
     const uint8_t *name,
38
     size_t name_size,
39
     uint8_t is_unicode,
40
     const libuna_utf8_character_t *utf8_string,
41
     size_t utf8_string_length,
42
     uint8_t use_case_folding,
43
     libcerror_error_t **error )
44
0
{
45
0
  static char *function                       = "libfsfat_name_compare_with_utf8_string";
46
0
  libuna_unicode_character_t name_character   = 0;
47
0
  libuna_unicode_character_t string_character = 0;
48
0
  size_t name_index                           = 0;
49
0
  size_t utf8_string_index                    = 0;
50
51
0
  if( name == NULL )
52
0
  {
53
0
    libcerror_error_set(
54
0
     error,
55
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57
0
     "%s: invalid UTF-16 encoded name.",
58
0
     function );
59
60
0
    return( -1 );
61
0
  }
62
0
  if( name_size > (size_t) SSIZE_MAX )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
67
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
68
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
0
  if( name_size == 0 )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
78
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
79
0
     "%s: missing UTF-16 encoded name value.",
80
0
     function );
81
82
0
    return( -1 );
83
0
  }
84
0
  if( utf8_string == NULL )
85
0
  {
86
0
    libcerror_error_set(
87
0
     error,
88
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
89
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
90
0
     "%s: invalid UTF-8 string.",
91
0
     function );
92
93
0
    return( -1 );
94
0
  }
95
0
  if( utf8_string_length > (size_t) SSIZE_MAX )
96
0
  {
97
0
    libcerror_error_set(
98
0
     error,
99
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
100
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
101
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
102
0
     function );
103
104
0
    return( -1 );
105
0
  }
106
0
  if( is_unicode != 0 )
107
0
  {
108
    /* Check if the UTF-16 stream is terminated with zero bytes
109
     */
110
0
    if( ( name_size >= 2 )
111
0
     && ( name[ name_size - 2 ] == 0 )
112
0
     && ( name[ name_size - 1 ] == 0 ) )
113
0
    {
114
0
      name_size -= 2;
115
0
    }
116
0
  }
117
0
  else
118
0
  {
119
    /* Check if the byte stream is terminated with a zero byte
120
     */
121
0
    if( ( name_size >= 1 )
122
0
     && ( name[ name_size - 1 ] == 0 ) )
123
0
    {
124
0
      name_size -= 1;
125
0
    }
126
0
  }
127
0
  if( ( utf8_string_length >= 1 )
128
0
   && ( utf8_string[ utf8_string_length - 1 ] == 0 ) )
129
0
  {
130
0
    utf8_string_length -= 1;
131
0
  }
132
0
  while( ( name_index < name_size )
133
0
      && ( utf8_string_index < utf8_string_length ) )
134
0
  {
135
0
    if( is_unicode != 0 )
136
0
    {
137
0
      if( libuna_unicode_character_copy_from_utf16_stream(
138
0
           &name_character,
139
0
           name,
140
0
           name_size,
141
0
           &name_index,
142
0
           LIBUNA_ENDIAN_LITTLE,
143
0
           error ) != 1 )
144
0
      {
145
0
        libcerror_error_set(
146
0
         error,
147
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
148
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
149
0
         "%s: unable to copy UTF-16 encoded name to Unicode character.",
150
0
         function );
151
152
0
        return( -1 );
153
0
      }
154
0
    }
155
0
    else
156
0
    {
157
/* TODO add codepage support */
158
0
      if( libuna_unicode_character_copy_from_byte_stream(
159
0
           &name_character,
160
0
           name,
161
0
           name_size,
162
0
           &name_index,
163
0
           LIBUNA_CODEPAGE_ASCII,
164
0
           error ) != 1 )
165
0
      {
166
0
        libcerror_error_set(
167
0
         error,
168
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
169
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
170
0
         "%s: unable to copy byte encoded name to Unicode character.",
171
0
         function );
172
173
0
        return( -1 );
174
0
      }
175
0
    }
176
0
    if( libuna_unicode_character_copy_from_utf8(
177
0
         &string_character,
178
0
         utf8_string,
179
0
         utf8_string_length,
180
0
         &utf8_string_index,
181
0
         error ) != 1 )
182
0
    {
183
0
      libcerror_error_set(
184
0
       error,
185
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
187
0
       "%s: unable to copy UTF-8 string to Unicode character.",
188
0
       function );
189
190
0
      return( -1 );
191
0
    }
192
0
    if( use_case_folding != 0 )
193
0
    {
194
0
      name_character   = (libuna_unicode_character_t) towupper( (wint_t) name_character );
195
0
      string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character );
196
0
    }
197
0
    if( string_character < name_character )
198
0
    {
199
0
      return( LIBUNA_COMPARE_LESS );
200
0
    }
201
0
    else if( string_character > name_character )
202
0
    {
203
0
      return( LIBUNA_COMPARE_GREATER );
204
0
    }
205
0
  }
206
0
  if( utf8_string_index < utf8_string_length )
207
0
  {
208
0
    return( LIBUNA_COMPARE_GREATER );
209
0
  }
210
0
  else if( name_index < name_size )
211
0
  {
212
0
    return( LIBUNA_COMPARE_LESS );
213
0
  }
214
0
  return( LIBUNA_COMPARE_EQUAL );
215
0
}
216
217
/* Compares an UTF-16 string with an UTF-16 encoded name
218
 * Returns LIBUNA_COMPARE_LESS, LIBUNA_COMPARE_EQUAL, LIBUNA_COMPARE_GREATER if successful or -1 on error
219
 */
220
int libfsfat_name_compare_with_utf16_string(
221
     const uint8_t *name,
222
     size_t name_size,
223
     uint8_t is_unicode,
224
     const libuna_utf16_character_t *utf16_string,
225
     size_t utf16_string_length,
226
     uint8_t use_case_folding,
227
     libcerror_error_t **error )
228
0
{
229
0
  static char *function                       = "libfsfat_name_compare_with_utf16_string";
230
0
  libuna_unicode_character_t name_character   = 0;
231
0
  libuna_unicode_character_t string_character = 0;
232
0
  size_t name_index                           = 0;
233
0
  size_t utf16_string_index                   = 0;
234
235
0
  if( name == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241
0
     "%s: invalid UTF-16 encoded name.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
0
  if( name_size > (size_t) SSIZE_MAX )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
252
0
     "%s: invalid UTF-16 encoded name size value exceeds maximum.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
0
  if( name_size == 0 )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_ZERO_OR_LESS,
263
0
     "%s: missing UTF-16 encoded name value.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
0
  if( utf16_string == NULL )
269
0
  {
270
0
    libcerror_error_set(
271
0
     error,
272
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
273
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
274
0
     "%s: invalid UTF-16 string.",
275
0
     function );
276
277
0
    return( -1 );
278
0
  }
279
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
280
0
  {
281
0
    libcerror_error_set(
282
0
     error,
283
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
284
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
285
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
286
0
     function );
287
288
0
    return( -1 );
289
0
  }
290
0
  if( is_unicode != 0 )
291
0
  {
292
    /* Check if the UTF-16 stream is terminated with zero bytes
293
     */
294
0
    if( ( name_size >= 2 )
295
0
     && ( name[ name_size - 2 ] == 0 )
296
0
     && ( name[ name_size - 1 ] == 0 ) )
297
0
    {
298
0
      name_size -= 2;
299
0
    }
300
0
  }
301
0
  else
302
0
  {
303
    /* Check if the byte stream is terminated with a zero byte
304
     */
305
0
    if( ( name_size >= 1 )
306
0
     && ( name[ name_size - 1 ] == 0 ) )
307
0
    {
308
0
      name_size -= 1;
309
0
    }
310
0
  }
311
0
  if( ( utf16_string_length >= 1 )
312
0
   && ( utf16_string[ utf16_string_length - 1 ] == 0 ) )
313
0
  {
314
0
    utf16_string_length -= 1;
315
0
  }
316
0
  while( ( name_index < name_size )
317
0
      && ( utf16_string_index < utf16_string_length ) )
318
0
  {
319
0
    if( is_unicode != 0 )
320
0
    {
321
0
      if( libuna_unicode_character_copy_from_utf16_stream(
322
0
           &name_character,
323
0
           name,
324
0
           name_size,
325
0
           &name_index,
326
0
           LIBUNA_ENDIAN_LITTLE,
327
0
           error ) != 1 )
328
0
      {
329
0
        libcerror_error_set(
330
0
         error,
331
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
332
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
333
0
         "%s: unable to copy UTF-16 encoded name to Unicode character.",
334
0
         function );
335
336
0
        return( -1 );
337
0
      }
338
0
    }
339
0
    else
340
0
    {
341
/* TODO add codepage support */
342
0
      if( libuna_unicode_character_copy_from_byte_stream(
343
0
           &name_character,
344
0
           name,
345
0
           name_size,
346
0
           &name_index,
347
0
           LIBUNA_CODEPAGE_ASCII,
348
0
           error ) != 1 )
349
0
      {
350
0
        libcerror_error_set(
351
0
         error,
352
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
353
0
         LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
354
0
         "%s: unable to copy byte encoded name to Unicode character.",
355
0
         function );
356
357
0
        return( -1 );
358
0
      }
359
0
    }
360
0
    if( libuna_unicode_character_copy_from_utf16(
361
0
         &string_character,
362
0
         utf16_string,
363
0
         utf16_string_length,
364
0
         &utf16_string_index,
365
0
         error ) != 1 )
366
0
    {
367
0
      libcerror_error_set(
368
0
       error,
369
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
370
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
371
0
       "%s: unable to copy UTF-16 string to Unicode character.",
372
0
       function );
373
374
0
      return( -1 );
375
0
    }
376
0
    if( use_case_folding != 0 )
377
0
    {
378
0
      name_character   = (libuna_unicode_character_t) towupper( (wint_t) name_character );
379
0
      string_character = (libuna_unicode_character_t) towupper( (wint_t) string_character );
380
0
    }
381
0
    if( string_character < name_character )
382
0
    {
383
0
      return( LIBUNA_COMPARE_LESS );
384
0
    }
385
0
    else if( string_character > name_character )
386
0
    {
387
0
      return( LIBUNA_COMPARE_GREATER );
388
0
    }
389
0
  }
390
0
  if( utf16_string_index < utf16_string_length )
391
0
  {
392
0
    return( LIBUNA_COMPARE_GREATER );
393
0
  }
394
0
  else if( name_index < name_size )
395
0
  {
396
0
    return( LIBUNA_COMPARE_LESS );
397
0
  }
398
0
  return( LIBUNA_COMPARE_EQUAL );
399
0
}
400