1 /*
2 * Name hash functions
3 *
4 * Copyright (C) 2018-2021, 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 <memory.h>
24 #include <types.h>
25
26 #include "libfsapfs_checksum.h"
27 #include "libfsapfs_libcerror.h"
28 #include "libfsapfs_libcnotify.h"
29 #include "libfsapfs_libuna.h"
30 #include "libfsapfs_name.h"
31
32 libfsapfs_name_decomposition_mapping_t special_case_folding_000000df = { 2, { 0x00000073, 0x00000073 } };
33 libfsapfs_name_decomposition_mapping_t special_case_folding_00000130 = { 2, { 0x00000069, 0x00000307 } };
34 libfsapfs_name_decomposition_mapping_t special_case_folding_00000149 = { 2, { 0x000002bc, 0x0000006e } };
35 libfsapfs_name_decomposition_mapping_t special_case_folding_00000587 = { 2, { 0x00000565, 0x00000582 } };
36 libfsapfs_name_decomposition_mapping_t special_case_folding_00001e9a = { 2, { 0x00000061, 0x000002be } };
37
38 libfsapfs_name_decomposition_mapping_t special_case_folding_00001f80[ 48 ] = {
39 /* 00001f80 */ { 3, { 0x000003b1, 0x00000313, 0x000003b9 } },
40 /* 00001f81 */ { 3, { 0x000003b1, 0x00000314, 0x000003b9 } },
41 /* 00001f82 */ { 4, { 0x000003b1, 0x00000313, 0x00000300, 0x000003b9 } },
42 /* 00001f83 */ { 4, { 0x000003b1, 0x00000314, 0x00000300, 0x000003b9 } },
43 /* 00001f84 */ { 4, { 0x000003b1, 0x00000313, 0x00000301, 0x000003b9 } },
44 /* 00001f85 */ { 4, { 0x000003b1, 0x00000314, 0x00000301, 0x000003b9 } },
45 /* 00001f86 */ { 4, { 0x000003b1, 0x00000313, 0x00000342, 0x000003b9 } },
46 /* 00001f87 */ { 4, { 0x000003b1, 0x00000314, 0x00000342, 0x000003b9 } },
47 /* 00001f88 */ { 3, { 0x000003b1, 0x00000313, 0x000003b9 } },
48 /* 00001f89 */ { 3, { 0x000003b1, 0x00000314, 0x000003b9 } },
49 /* 00001f8a */ { 4, { 0x000003b1, 0x00000313, 0x00000300, 0x000003b9 } },
50 /* 00001f8b */ { 4, { 0x000003b1, 0x00000314, 0x00000300, 0x000003b9 } },
51 /* 00001f8c */ { 4, { 0x000003b1, 0x00000313, 0x00000301, 0x000003b9 } },
52 /* 00001f8d */ { 4, { 0x000003b1, 0x00000314, 0x00000301, 0x000003b9 } },
53 /* 00001f8e */ { 4, { 0x000003b1, 0x00000313, 0x00000342, 0x000003b9 } },
54 /* 00001f8f */ { 4, { 0x000003b1, 0x00000314, 0x00000342, 0x000003b9 } },
55 /* 00001f90 */ { 3, { 0x000003b7, 0x00000313, 0x000003b9 } },
56 /* 00001f91 */ { 3, { 0x000003b7, 0x00000314, 0x000003b9 } },
57 /* 00001f92 */ { 4, { 0x000003b7, 0x00000313, 0x00000300, 0x000003b9 } },
58 /* 00001f93 */ { 4, { 0x000003b7, 0x00000314, 0x00000300, 0x000003b9 } },
59 /* 00001f94 */ { 4, { 0x000003b7, 0x00000313, 0x00000301, 0x000003b9 } },
60 /* 00001f95 */ { 4, { 0x000003b7, 0x00000314, 0x00000301, 0x000003b9 } },
61 /* 00001f96 */ { 4, { 0x000003b7, 0x00000313, 0x00000342, 0x000003b9 } },
62 /* 00001f97 */ { 4, { 0x000003b7, 0x00000314, 0x00000342, 0x000003b9 } },
63 /* 00001f98 */ { 3, { 0x000003b7, 0x00000313, 0x000003b9 } },
64 /* 00001f99 */ { 3, { 0x000003b7, 0x00000314, 0x000003b9 } },
65 /* 00001f9a */ { 4, { 0x000003b7, 0x00000313, 0x00000300, 0x000003b9 } },
66 /* 00001f9b */ { 4, { 0x000003b7, 0x00000314, 0x00000300, 0x000003b9 } },
67 /* 00001f9c */ { 4, { 0x000003b7, 0x00000313, 0x00000301, 0x000003b9 } },
68 /* 00001f9d */ { 4, { 0x000003b7, 0x00000314, 0x00000301, 0x000003b9 } },
69 /* 00001f9e */ { 4, { 0x000003b7, 0x00000313, 0x00000342, 0x000003b9 } },
70 /* 00001f9f */ { 4, { 0x000003b7, 0x00000314, 0x00000342, 0x000003b9 } },
71 /* 00001fa0 */ { 3, { 0x000003c9, 0x00000313, 0x000003b9 } },
72 /* 00001fa1 */ { 3, { 0x000003c9, 0x00000314, 0x000003b9 } },
73 /* 00001fa2 */ { 4, { 0x000003c9, 0x00000313, 0x00000300, 0x000003b9 } },
74 /* 00001fa3 */ { 4, { 0x000003c9, 0x00000314, 0x00000300, 0x000003b9 } },
75 /* 00001fa4 */ { 4, { 0x000003c9, 0x00000313, 0x00000301, 0x000003b9 } },
76 /* 00001fa5 */ { 4, { 0x000003c9, 0x00000314, 0x00000301, 0x000003b9 } },
77 /* 00001fa6 */ { 4, { 0x000003c9, 0x00000313, 0x00000342, 0x000003b9 } },
78 /* 00001fa7 */ { 4, { 0x000003c9, 0x00000314, 0x00000342, 0x000003b9 } },
79 /* 00001fa8 */ { 3, { 0x000003c9, 0x00000313, 0x000003b9 } },
80 /* 00001fa9 */ { 3, { 0x000003c9, 0x00000314, 0x000003b9 } },
81 /* 00001faa */ { 4, { 0x000003c9, 0x00000313, 0x00000300, 0x000003b9 } },
82 /* 00001fab */ { 4, { 0x000003c9, 0x00000314, 0x00000300, 0x000003b9 } },
83 /* 00001fac */ { 4, { 0x000003c9, 0x00000313, 0x00000301, 0x000003b9 } },
84 /* 00001fad */ { 4, { 0x000003c9, 0x00000314, 0x00000301, 0x000003b9 } },
85 /* 00001fae */ { 4, { 0x000003c9, 0x00000313, 0x00000342, 0x000003b9 } },
86 /* 00001faf */ { 4, { 0x000003c9, 0x00000314, 0x00000342, 0x000003b9 } }
87 };
88
89 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb2 = { 3, { 0x000003b1, 0x00000300, 0x000003b9 } };
90 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb3 = { 2, { 0x000003b1, 0x000003b9 } };
91 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb4 = { 3, { 0x000003b1, 0x00000301, 0x000003b9 } };
92 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb6 = { 2, { 0x000003b1, 0x00000342 } };
93 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fb7 = { 3, { 0x000003b1, 0x00000342, 0x000003b9 } };
94 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fbc = { 2, { 0x000003b1, 0x000003b9 } };
95
96 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc2 = { 3, { 0x000003b7, 0x00000300, 0x000003b9 } };
97 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc3 = { 2, { 0x000003b7, 0x000003b9 } };
98 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc4 = { 3, { 0x000003b7, 0x00000301, 0x000003b9 } };
99 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc6 = { 2, { 0x000003b7, 0x00000342 } };
100 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fc7 = { 3, { 0x000003b7, 0x00000342, 0x000003b9 } };
101 libfsapfs_name_decomposition_mapping_t special_case_folding_00001fcc = { 2, { 0x000003b7, 0x000003b9 } };
102
103 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff2 = { 3, { 0x000003c9, 0x00000300, 0x000003b9 } };
104 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff3 = { 2, { 0x000003c9, 0x000003b9 } };
105 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff4 = { 3, { 0x000003c9, 0x00000301, 0x000003b9 } };
106 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff6 = { 2, { 0x000003c9, 0x00000342 } };
107 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ff7 = { 3, { 0x000003c9, 0x00000342, 0x000003b9 } };
108 libfsapfs_name_decomposition_mapping_t special_case_folding_00001ffc = { 2, { 0x000003c9, 0x000003b9 } };
109
110 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb00 = { 2, { 0x00000066, 0x00000066 } };
111 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb01 = { 2, { 0x00000066, 0x00000069 } };
112 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb02 = { 2, { 0x00000066, 0x0000006c } };
113 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb03 = { 3, { 0x00000066, 0x00000066, 0x00000069 } };
114 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb04 = { 3, { 0x00000066, 0x00000066, 0x0000006c } };
115 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb05 = { 2, { 0x00000073, 0x00000074 } };
116 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb06 = { 2, { 0x00000073, 0x00000074 } };
117
118 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb13 = { 2, { 0x00000574, 0x00000576 } };
119 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb14 = { 2, { 0x00000574, 0x00000565 } };
120 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb15 = { 2, { 0x00000574, 0x0000056b } };
121 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb16 = { 2, { 0x0000057e, 0x00000576 } };
122 libfsapfs_name_decomposition_mapping_t special_case_folding_0000fb17 = { 2, { 0x00000574, 0x0000056d } };
123
124 /* Calculates the name hash of an UTF-8 formatted string
125 * Returns 1 if successful or -1 on error
126 */
libfsapfs_name_hash_calculate_from_utf8_string(uint32_t * name_hash,const uint8_t * utf8_string,size_t utf8_string_length,uint8_t use_case_folding,libcerror_error_t ** error)127 int libfsapfs_name_hash_calculate_from_utf8_string(
128 uint32_t *name_hash,
129 const uint8_t *utf8_string,
130 size_t utf8_string_length,
131 uint8_t use_case_folding,
132 libcerror_error_t **error )
133 {
134 libfsapfs_name_decomposition_mapping_t single_nfd_mapping = { 1, { 0 } };
135
136 libfsapfs_name_decomposition_mapping_t *nfd_mapping = NULL;
137 static char *function = "libfsapfs_name_hash_calculate_from_utf8_string";
138 libuna_unicode_character_t unicode_character = 0;
139 size_t utf8_string_index = 0;
140 uint32_t calculated_checksum = 0;
141 uint32_t checksum_table_index = 0;
142 uint8_t byte_value = 0;
143 uint8_t nfd_character_index = 0;
144
145 #if defined( HAVE_DEBUG_OUTPUT )
146 uint8_t utf32_stream[ 512 ];
147
148 size_t utf32_stream_index = 0;
149 #endif
150
151 if( name_hash == NULL )
152 {
153 libcerror_error_set(
154 error,
155 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
156 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
157 "%s: invalid name hash.",
158 function );
159
160 return( -1 );
161 }
162 if( libfsapfs_checksum_crc32_table_computed == 0 )
163 {
164 libfsapfs_checksum_initialize_crc32_table(
165 0x82f63b78UL );
166 }
167 calculated_checksum = 0xffffffffUL;
168
169 while( utf8_string_index < utf8_string_length )
170 {
171 if( libuna_unicode_character_copy_from_utf8(
172 &unicode_character,
173 utf8_string,
174 utf8_string_length,
175 &utf8_string_index,
176 error ) != 1 )
177 {
178 libcerror_error_set(
179 error,
180 LIBCERROR_ERROR_DOMAIN_CONVERSION,
181 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
182 "%s: unable to copy Unicode character from UTF-8 string.",
183 function );
184
185 return( -1 );
186 }
187 if( unicode_character == 0 )
188 {
189 break;
190 }
191 if( use_case_folding != 0 )
192 {
193 libfsapfs_name_get_case_folding_mapping(
194 unicode_character );
195
196 /* Overload the NFD mapping to handle special case folding
197 */
198 if( ( unicode_character >= 0x00001f80UL )
199 && ( unicode_character <= 0x00001fafUL ) )
200 {
201 nfd_mapping = &( special_case_folding_00001f80[ unicode_character - 0x00001f80UL ] );
202 }
203 else switch( unicode_character )
204 {
205 case 0x000000dfUL:
206 nfd_mapping = &special_case_folding_000000df;
207 break;
208
209 case 0x00000130UL:
210 nfd_mapping = &special_case_folding_00000130;
211 break;
212
213 case 0x00000149UL:
214 nfd_mapping = &special_case_folding_00000149;
215 break;
216
217 case 0x00000587UL:
218 nfd_mapping = &special_case_folding_00000587;
219 break;
220
221 case 0x00001e9aUL:
222 nfd_mapping = &special_case_folding_00001e9a;
223 break;
224
225 case 0x00001fb2UL:
226 nfd_mapping = &special_case_folding_00001fb2;
227 break;
228
229 case 0x00001fb3UL:
230 nfd_mapping = &special_case_folding_00001fb3;
231 break;
232
233 case 0x00001fb4UL:
234 nfd_mapping = &special_case_folding_00001fb4;
235 break;
236
237 case 0x00001fb6UL:
238 nfd_mapping = &special_case_folding_00001fb6;
239 break;
240
241 case 0x00001fb7UL:
242 nfd_mapping = &special_case_folding_00001fb7;
243 break;
244
245 case 0x00001fbcUL:
246 nfd_mapping = &special_case_folding_00001fbc;
247 break;
248
249 case 0x00001fc2UL:
250 nfd_mapping = &special_case_folding_00001fc2;
251 break;
252
253 case 0x00001fc3UL:
254 nfd_mapping = &special_case_folding_00001fc3;
255 break;
256
257 case 0x00001fc4UL:
258 nfd_mapping = &special_case_folding_00001fc4;
259 break;
260
261 case 0x00001fc6UL:
262 nfd_mapping = &special_case_folding_00001fc6;
263 break;
264
265 case 0x00001fc7UL:
266 nfd_mapping = &special_case_folding_00001fc7;
267 break;
268
269 case 0x00001fccUL:
270 nfd_mapping = &special_case_folding_00001fcc;
271 break;
272
273 case 0x00001ff2UL:
274 nfd_mapping = &special_case_folding_00001ff2;
275 break;
276
277 case 0x00001ff3UL:
278 nfd_mapping = &special_case_folding_00001ff3;
279 break;
280
281 case 0x00001ff4UL:
282 nfd_mapping = &special_case_folding_00001ff4;
283 break;
284
285 case 0x00001ff6UL:
286 nfd_mapping = &special_case_folding_00001ff6;
287 break;
288
289 case 0x00001ff7UL:
290 nfd_mapping = &special_case_folding_00001ff7;
291 break;
292
293 case 0x00001ffcUL:
294 nfd_mapping = &special_case_folding_00001ffc;
295 break;
296
297 case 0x0000fb00UL:
298 nfd_mapping = &special_case_folding_0000fb00;
299 break;
300
301 case 0x0000fb01UL:
302 nfd_mapping = &special_case_folding_0000fb01;
303 break;
304
305 case 0x0000fb02UL:
306 nfd_mapping = &special_case_folding_0000fb02;
307 break;
308
309 case 0x0000fb03UL:
310 nfd_mapping = &special_case_folding_0000fb03;
311 break;
312
313 case 0x0000fb04UL:
314 nfd_mapping = &special_case_folding_0000fb04;
315 break;
316
317 case 0x0000fb05UL:
318 nfd_mapping = &special_case_folding_0000fb05;
319 break;
320
321 case 0x0000fb06UL:
322 nfd_mapping = &special_case_folding_0000fb06;
323 break;
324
325 case 0x0000fb13UL:
326 nfd_mapping = &special_case_folding_0000fb13;
327 break;
328
329 case 0x0000fb14UL:
330 nfd_mapping = &special_case_folding_0000fb14;
331 break;
332
333 case 0x0000fb15UL:
334 nfd_mapping = &special_case_folding_0000fb15;
335 break;
336
337 case 0x0000fb16UL:
338 nfd_mapping = &special_case_folding_0000fb16;
339 break;
340
341 case 0x0000fb17UL:
342 nfd_mapping = &special_case_folding_0000fb17;
343 break;
344
345 default:
346 libfsapfs_name_get_decomposition_mapping(
347 unicode_character,
348 nfd_mapping,
349 single_nfd_mapping );
350 break;
351 }
352 }
353 else
354 {
355 libfsapfs_name_get_decomposition_mapping(
356 unicode_character,
357 nfd_mapping,
358 single_nfd_mapping );
359 }
360 for( nfd_character_index = 0;
361 nfd_character_index < nfd_mapping->number_of_characters;
362 nfd_character_index++ )
363 {
364 unicode_character = nfd_mapping->characters[ nfd_character_index ];
365
366 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
367 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
368 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
369 unicode_character >>= 8;
370
371 #if defined( HAVE_DEBUG_OUTPUT )
372 if( utf32_stream_index < 512 )
373 {
374 utf32_stream[ utf32_stream_index++ ] = byte_value;
375 }
376 #endif
377
378 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
379 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
380 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
381 unicode_character >>= 8;
382
383 #if defined( HAVE_DEBUG_OUTPUT )
384 if( utf32_stream_index < 512 )
385 {
386 utf32_stream[ utf32_stream_index++ ] = byte_value;
387 }
388 #endif
389
390 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
391 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
392 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
393 unicode_character >>= 8;
394
395 #if defined( HAVE_DEBUG_OUTPUT )
396 if( utf32_stream_index < 512 )
397 {
398 utf32_stream[ utf32_stream_index++ ] = byte_value;
399 }
400 #endif
401
402 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
403 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
404 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
405
406 #if defined( HAVE_DEBUG_OUTPUT )
407 if( utf32_stream_index < 512 )
408 {
409 utf32_stream[ utf32_stream_index++ ] = byte_value;
410 }
411 #endif
412 }
413 }
414 *name_hash = calculated_checksum & 0x003fffffUL;
415
416 #if defined( HAVE_DEBUG_OUTPUT )
417 if( libcnotify_verbose != 0 )
418 {
419 libcnotify_printf(
420 "%s: UTF-32 stream data:\n",
421 function );
422 libcnotify_print_data(
423 utf32_stream,
424 utf32_stream_index,
425 0 );
426
427 libcnotify_printf(
428 "%s: CRC-32 checkum\t\t: 0x%08" PRIx32 "\n",
429 function,
430 calculated_checksum );
431
432 libcnotify_printf(
433 "%s: name hash\t\t: 0x%06" PRIx32 "\n",
434 function,
435 *name_hash );
436
437 libcnotify_printf(
438 "\n" );
439 }
440 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
441
442 return( 1 );
443 }
444
445 /* Calculates the name hash of an UTF-16 formatted string
446 * Returns 1 if successful or -1 on error
447 */
libfsapfs_name_hash_calculate_from_utf16_string(uint32_t * name_hash,const uint16_t * utf16_string,size_t utf16_string_length,uint8_t use_case_folding,libcerror_error_t ** error)448 int libfsapfs_name_hash_calculate_from_utf16_string(
449 uint32_t *name_hash,
450 const uint16_t *utf16_string,
451 size_t utf16_string_length,
452 uint8_t use_case_folding,
453 libcerror_error_t **error )
454 {
455 libfsapfs_name_decomposition_mapping_t single_nfd_mapping = { 1, { 0 } };
456
457 libfsapfs_name_decomposition_mapping_t *nfd_mapping = NULL;
458 static char *function = "libfsapfs_name_hash_calculate_from_utf16_string";
459 libuna_unicode_character_t unicode_character = 0;
460 size_t utf16_string_index = 0;
461 uint32_t calculated_checksum = 0;
462 uint32_t checksum_table_index = 0;
463 uint8_t byte_value = 0;
464 uint8_t nfd_character_index = 0;
465
466 #if defined( HAVE_DEBUG_OUTPUT )
467 uint8_t utf32_stream[ 512 ];
468
469 size_t utf32_stream_index = 0;
470 #endif
471
472 if( name_hash == NULL )
473 {
474 libcerror_error_set(
475 error,
476 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
477 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
478 "%s: invalid name hash.",
479 function );
480
481 return( -1 );
482 }
483 if( libfsapfs_checksum_crc32_table_computed == 0 )
484 {
485 libfsapfs_checksum_initialize_crc32_table(
486 0x82f63b78UL );
487 }
488 calculated_checksum = 0xffffffffUL;
489
490 while( utf16_string_index < utf16_string_length )
491 {
492 if( libuna_unicode_character_copy_from_utf16(
493 &unicode_character,
494 utf16_string,
495 utf16_string_length,
496 &utf16_string_index,
497 error ) != 1 )
498 {
499 libcerror_error_set(
500 error,
501 LIBCERROR_ERROR_DOMAIN_CONVERSION,
502 LIBCERROR_CONVERSION_ERROR_INPUT_FAILED,
503 "%s: unable to copy Unicode character from UTF-16 string.",
504 function );
505
506 return( -1 );
507 }
508 if( unicode_character == 0 )
509 {
510 break;
511 }
512 if( use_case_folding != 0 )
513 {
514 libfsapfs_name_get_case_folding_mapping(
515 unicode_character );
516
517 /* Overload the NFD mapping to handle special case folding
518 */
519 if( ( unicode_character >= 0x00001f80UL )
520 && ( unicode_character <= 0x00001fafUL ) )
521 {
522 nfd_mapping = &( special_case_folding_00001f80[ unicode_character - 0x00001f80UL ] );
523 }
524 else switch( unicode_character )
525 {
526 case 0x000000dfUL:
527 nfd_mapping = &special_case_folding_000000df;
528 break;
529
530 case 0x00000130UL:
531 nfd_mapping = &special_case_folding_00000130;
532 break;
533
534 case 0x00000149UL:
535 nfd_mapping = &special_case_folding_00000149;
536 break;
537
538 case 0x00000587UL:
539 nfd_mapping = &special_case_folding_00000587;
540 break;
541
542 case 0x00001e9aUL:
543 nfd_mapping = &special_case_folding_00001e9a;
544 break;
545
546 case 0x00001fb2UL:
547 nfd_mapping = &special_case_folding_00001fb2;
548 break;
549
550 case 0x00001fb3UL:
551 nfd_mapping = &special_case_folding_00001fb3;
552 break;
553
554 case 0x00001fb4UL:
555 nfd_mapping = &special_case_folding_00001fb4;
556 break;
557
558 case 0x00001fb6UL:
559 nfd_mapping = &special_case_folding_00001fb6;
560 break;
561
562 case 0x00001fb7UL:
563 nfd_mapping = &special_case_folding_00001fb7;
564 break;
565
566 case 0x00001fbcUL:
567 nfd_mapping = &special_case_folding_00001fbc;
568 break;
569
570 case 0x00001fc2UL:
571 nfd_mapping = &special_case_folding_00001fc2;
572 break;
573
574 case 0x00001fc3UL:
575 nfd_mapping = &special_case_folding_00001fc3;
576 break;
577
578 case 0x00001fc4UL:
579 nfd_mapping = &special_case_folding_00001fc4;
580 break;
581
582 case 0x00001fc6UL:
583 nfd_mapping = &special_case_folding_00001fc6;
584 break;
585
586 case 0x00001fc7UL:
587 nfd_mapping = &special_case_folding_00001fc7;
588 break;
589
590 case 0x00001fccUL:
591 nfd_mapping = &special_case_folding_00001fcc;
592 break;
593
594 case 0x00001ff2UL:
595 nfd_mapping = &special_case_folding_00001ff2;
596 break;
597
598 case 0x00001ff3UL:
599 nfd_mapping = &special_case_folding_00001ff3;
600 break;
601
602 case 0x00001ff4UL:
603 nfd_mapping = &special_case_folding_00001ff4;
604 break;
605
606 case 0x00001ff6UL:
607 nfd_mapping = &special_case_folding_00001ff6;
608 break;
609
610 case 0x00001ff7UL:
611 nfd_mapping = &special_case_folding_00001ff7;
612 break;
613
614 case 0x00001ffcUL:
615 nfd_mapping = &special_case_folding_00001ffc;
616 break;
617
618 case 0x0000fb00UL:
619 nfd_mapping = &special_case_folding_0000fb00;
620 break;
621
622 case 0x0000fb01UL:
623 nfd_mapping = &special_case_folding_0000fb01;
624 break;
625
626 case 0x0000fb02UL:
627 nfd_mapping = &special_case_folding_0000fb02;
628 break;
629
630 case 0x0000fb03UL:
631 nfd_mapping = &special_case_folding_0000fb03;
632 break;
633
634 case 0x0000fb04UL:
635 nfd_mapping = &special_case_folding_0000fb04;
636 break;
637
638 case 0x0000fb05UL:
639 nfd_mapping = &special_case_folding_0000fb05;
640 break;
641
642 case 0x0000fb06UL:
643 nfd_mapping = &special_case_folding_0000fb06;
644 break;
645
646 case 0x0000fb13UL:
647 nfd_mapping = &special_case_folding_0000fb13;
648 break;
649
650 case 0x0000fb14UL:
651 nfd_mapping = &special_case_folding_0000fb14;
652 break;
653
654 case 0x0000fb15UL:
655 nfd_mapping = &special_case_folding_0000fb15;
656 break;
657
658 case 0x0000fb16UL:
659 nfd_mapping = &special_case_folding_0000fb16;
660 break;
661
662 case 0x0000fb17UL:
663 nfd_mapping = &special_case_folding_0000fb17;
664 break;
665
666 default:
667 libfsapfs_name_get_decomposition_mapping(
668 unicode_character,
669 nfd_mapping,
670 single_nfd_mapping );
671 break;
672 }
673 }
674 else
675 {
676 libfsapfs_name_get_decomposition_mapping(
677 unicode_character,
678 nfd_mapping,
679 single_nfd_mapping );
680 }
681 for( nfd_character_index = 0;
682 nfd_character_index < nfd_mapping->number_of_characters;
683 nfd_character_index++ )
684 {
685 unicode_character = nfd_mapping->characters[ nfd_character_index ];
686
687 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
688 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
689 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
690 unicode_character >>= 8;
691
692 #if defined( HAVE_DEBUG_OUTPUT )
693 if( utf32_stream_index < 512 )
694 {
695 utf32_stream[ utf32_stream_index++ ] = byte_value;
696 }
697 #endif
698
699 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
700 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
701 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
702 unicode_character >>= 8;
703
704 #if defined( HAVE_DEBUG_OUTPUT )
705 if( utf32_stream_index < 512 )
706 {
707 utf32_stream[ utf32_stream_index++ ] = byte_value;
708 }
709 #endif
710
711 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
712 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
713 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
714 unicode_character >>= 8;
715
716 #if defined( HAVE_DEBUG_OUTPUT )
717 if( utf32_stream_index < 512 )
718 {
719 utf32_stream[ utf32_stream_index++ ] = byte_value;
720 }
721 #endif
722
723 byte_value = (uint8_t) ( unicode_character & 0x000000ffUL );
724 checksum_table_index = ( calculated_checksum ^ (uint32_t) byte_value ) & 0x000000ffUL;
725 calculated_checksum = libfsapfs_checksum_crc32_table[ checksum_table_index ] ^ ( calculated_checksum >> 8 );
726
727 #if defined( HAVE_DEBUG_OUTPUT )
728 if( utf32_stream_index < 512 )
729 {
730 utf32_stream[ utf32_stream_index++ ] = byte_value;
731 }
732 #endif
733 }
734 }
735 *name_hash = calculated_checksum & 0x003fffffUL;
736
737 #if defined( HAVE_DEBUG_OUTPUT )
738 if( libcnotify_verbose != 0 )
739 {
740 libcnotify_printf(
741 "%s: UTF-32 stream data:\n",
742 function );
743 libcnotify_print_data(
744 utf32_stream,
745 utf32_stream_index,
746 0 );
747
748 libcnotify_printf(
749 "%s: CRC-32 checkum\t\t: 0x%08" PRIx32 "\n",
750 function,
751 calculated_checksum );
752
753 libcnotify_printf(
754 "%s: name hash\t\t: 0x%06" PRIx32 "\n",
755 function,
756 *name_hash );
757
758 libcnotify_printf(
759 "\n" );
760 }
761 #endif /* defined( HAVE_DEBUG_OUTPUT ) */
762
763 return( 1 );
764 }
765
766