xref: /linux/fs/hfsplus/unicode.c (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  linux/fs/hfsplus/unicode.c
4  *
5  * Copyright (C) 2001
6  * Brad Boyer (flar@allandria.com)
7  * (C) 2003 Ardis Technologies <roman@ardistech.com>
8  *
9  * Handler routines for unicode strings
10  */
11 
12 #include <linux/types.h>
13 #include <linux/nls.h>
14 
15 #include <kunit/visibility.h>
16 
17 #include "hfsplus_fs.h"
18 #include "hfsplus_raw.h"
19 #include "unicode.h"
20 
21 /* Fold the case of a unicode char, given the 16 bit value */
22 /* Returns folded char, or 0 if ignorable */
23 static inline u16 case_fold(u16 c)
24 {
25 	u16 tmp;
26 
27 	tmp = hfsplus_case_fold_table[c >> 8];
28 	if (tmp)
29 		tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
30 	else
31 		tmp = c;
32 	return tmp;
33 }
34 
35 /* Compare unicode strings, return values like normal strcmp */
36 int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
37 		       const struct hfsplus_unistr *s2)
38 {
39 	u16 len1, len2, c1, c2;
40 	const hfsplus_unichr *p1, *p2;
41 
42 	len1 = be16_to_cpu(s1->length);
43 	len2 = be16_to_cpu(s2->length);
44 	p1 = s1->unicode;
45 	p2 = s2->unicode;
46 
47 	if (len1 > HFSPLUS_MAX_STRLEN) {
48 		len1 = HFSPLUS_MAX_STRLEN;
49 		pr_err("invalid length %u has been corrected to %d\n",
50 			be16_to_cpu(s1->length), len1);
51 	}
52 
53 	if (len2 > HFSPLUS_MAX_STRLEN) {
54 		len2 = HFSPLUS_MAX_STRLEN;
55 		pr_err("invalid length %u has been corrected to %d\n",
56 			be16_to_cpu(s2->length), len2);
57 	}
58 
59 	while (1) {
60 		c1 = c2 = 0;
61 
62 		while (len1 && !c1) {
63 			c1 = case_fold(be16_to_cpu(*p1));
64 			p1++;
65 			len1--;
66 		}
67 		while (len2 && !c2) {
68 			c2 = case_fold(be16_to_cpu(*p2));
69 			p2++;
70 			len2--;
71 		}
72 
73 		if (c1 != c2)
74 			return (c1 < c2) ? -1 : 1;
75 		if (!c1 && !c2)
76 			return 0;
77 	}
78 }
79 EXPORT_SYMBOL_IF_KUNIT(hfsplus_strcasecmp);
80 
81 /* Compare names as a sequence of 16-bit unsigned integers */
82 int hfsplus_strcmp(const struct hfsplus_unistr *s1,
83 		   const struct hfsplus_unistr *s2)
84 {
85 	u16 len1, len2, c1, c2;
86 	const hfsplus_unichr *p1, *p2;
87 	int len;
88 
89 	len1 = be16_to_cpu(s1->length);
90 	len2 = be16_to_cpu(s2->length);
91 	p1 = s1->unicode;
92 	p2 = s2->unicode;
93 
94 	if (len1 > HFSPLUS_MAX_STRLEN) {
95 		len1 = HFSPLUS_MAX_STRLEN;
96 		pr_err("invalid length %u has been corrected to %d\n",
97 			be16_to_cpu(s1->length), len1);
98 	}
99 
100 	if (len2 > HFSPLUS_MAX_STRLEN) {
101 		len2 = HFSPLUS_MAX_STRLEN;
102 		pr_err("invalid length %u has been corrected to %d\n",
103 			be16_to_cpu(s2->length), len2);
104 	}
105 
106 	for (len = min(len1, len2); len > 0; len--) {
107 		c1 = be16_to_cpu(*p1);
108 		c2 = be16_to_cpu(*p2);
109 		if (c1 != c2)
110 			return c1 < c2 ? -1 : 1;
111 		p1++;
112 		p2++;
113 	}
114 
115 	return len1 < len2 ? -1 :
116 	       len1 > len2 ? 1 : 0;
117 }
118 EXPORT_SYMBOL_IF_KUNIT(hfsplus_strcmp);
119 
120 #define Hangul_SBase	0xac00
121 #define Hangul_LBase	0x1100
122 #define Hangul_VBase	0x1161
123 #define Hangul_TBase	0x11a7
124 #define Hangul_SCount	11172
125 #define Hangul_LCount	19
126 #define Hangul_VCount	21
127 #define Hangul_TCount	28
128 #define Hangul_NCount	(Hangul_VCount * Hangul_TCount)
129 
130 
131 static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
132 {
133 	int i, s, e;
134 
135 	s = 1;
136 	e = p[1];
137 	if (!e || cc < p[s * 2] || cc > p[e * 2])
138 		return NULL;
139 	do {
140 		i = (s + e) / 2;
141 		if (cc > p[i * 2])
142 			s = i + 1;
143 		else if (cc < p[i * 2])
144 			e = i - 1;
145 		else
146 			return hfsplus_compose_table + p[i * 2 + 1];
147 	} while (s <= e);
148 	return NULL;
149 }
150 
151 /*
152  * In HFS+, a filename can contain / because : is the separator.
153  * The slash is a valid filename character on macOS.
154  * But on Linux, / is the path separator and
155  * it cannot appear in a filename component.
156  * There's a parallel mapping for the NUL character (0 -> U+2400).
157  * NUL terminates strings in C/POSIX but is valid in HFS+ filenames.
158  */
159 static inline
160 void hfsplus_mac2linux_compatibility_check(u16 symbol, u16 *conversion,
161 					   int name_type)
162 {
163 	*conversion = symbol;
164 
165 	switch (name_type) {
166 	case HFS_XATTR_NAME:
167 		/* ignore conversion */
168 		return;
169 
170 	default:
171 		/* continue logic */
172 		break;
173 	}
174 
175 	switch (symbol) {
176 	case 0:
177 		*conversion = 0x2400;
178 		break;
179 	case '/':
180 		*conversion = ':';
181 		break;
182 	}
183 }
184 
185 static int hfsplus_uni2asc(struct super_block *sb,
186 			   const struct hfsplus_unistr *ustr,
187 			   int max_len, char *astr, int *len_p,
188 			   int name_type)
189 {
190 	const hfsplus_unichr *ip;
191 	struct nls_table *nls = HFSPLUS_SB(sb)->nls;
192 	u8 *op;
193 	u16 cc, c0, c1;
194 	u16 *ce1, *ce2;
195 	int i, len, ustrlen, res, compose;
196 
197 	op = astr;
198 	ip = ustr->unicode;
199 
200 	ustrlen = be16_to_cpu(ustr->length);
201 	if (ustrlen > max_len) {
202 		ustrlen = max_len;
203 		pr_err("invalid length %u has been corrected to %d\n",
204 			be16_to_cpu(ustr->length), ustrlen);
205 	}
206 
207 	len = *len_p;
208 	ce1 = NULL;
209 	compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
210 
211 	while (ustrlen > 0) {
212 		c0 = be16_to_cpu(*ip++);
213 		ustrlen--;
214 		/* search for single decomposed char */
215 		if (likely(compose))
216 			ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0);
217 		if (ce1)
218 			cc = ce1[0];
219 		else
220 			cc = 0;
221 		if (cc) {
222 			/* start of a possibly decomposed Hangul char */
223 			if (cc != 0xffff)
224 				goto done;
225 			if (!ustrlen)
226 				goto same;
227 			c1 = be16_to_cpu(*ip) - Hangul_VBase;
228 			if (c1 < Hangul_VCount) {
229 				/* compose the Hangul char */
230 				cc = (c0 - Hangul_LBase) * Hangul_VCount;
231 				cc = (cc + c1) * Hangul_TCount;
232 				cc += Hangul_SBase;
233 				ip++;
234 				ustrlen--;
235 				if (!ustrlen)
236 					goto done;
237 				c1 = be16_to_cpu(*ip) - Hangul_TBase;
238 				if (c1 > 0 && c1 < Hangul_TCount) {
239 					cc += c1;
240 					ip++;
241 					ustrlen--;
242 				}
243 				goto done;
244 			}
245 		}
246 		while (1) {
247 			/* main loop for common case of not composed chars */
248 			if (!ustrlen)
249 				goto same;
250 			c1 = be16_to_cpu(*ip);
251 			if (likely(compose))
252 				ce1 = hfsplus_compose_lookup(
253 					hfsplus_compose_table, c1);
254 			if (ce1)
255 				break;
256 			hfsplus_mac2linux_compatibility_check(c0, &c0,
257 							      name_type);
258 			res = nls->uni2char(c0, op, len);
259 			if (res < 0) {
260 				if (res == -ENAMETOOLONG)
261 					goto out;
262 				*op = '?';
263 				res = 1;
264 			}
265 			op += res;
266 			len -= res;
267 			c0 = c1;
268 			ip++;
269 			ustrlen--;
270 		}
271 		ce2 = hfsplus_compose_lookup(ce1, c0);
272 		if (ce2) {
273 			i = 1;
274 			while (i < ustrlen) {
275 				ce1 = hfsplus_compose_lookup(ce2,
276 					be16_to_cpu(ip[i]));
277 				if (!ce1)
278 					break;
279 				i++;
280 				ce2 = ce1;
281 			}
282 			cc = ce2[0];
283 			if (cc) {
284 				ip += i;
285 				ustrlen -= i;
286 				goto done;
287 			}
288 		}
289 same:
290 		hfsplus_mac2linux_compatibility_check(c0, &cc,
291 						      name_type);
292 done:
293 		res = nls->uni2char(cc, op, len);
294 		if (res < 0) {
295 			if (res == -ENAMETOOLONG)
296 				goto out;
297 			*op = '?';
298 			res = 1;
299 		}
300 		op += res;
301 		len -= res;
302 	}
303 	res = 0;
304 out:
305 	*len_p = (char *)op - astr;
306 	return res;
307 }
308 
309 inline int hfsplus_uni2asc_str(struct super_block *sb,
310 			       const struct hfsplus_unistr *ustr, char *astr,
311 			       int *len_p)
312 {
313 	return hfsplus_uni2asc(sb,
314 				ustr, HFSPLUS_MAX_STRLEN,
315 				astr, len_p,
316 				HFS_REGULAR_NAME);
317 }
318 EXPORT_SYMBOL_IF_KUNIT(hfsplus_uni2asc_str);
319 
320 inline int hfsplus_uni2asc_xattr_str(struct super_block *sb,
321 				     const struct hfsplus_attr_unistr *ustr,
322 				     char *astr, int *len_p)
323 {
324 	return hfsplus_uni2asc(sb, (const struct hfsplus_unistr *)ustr,
325 				HFSPLUS_ATTR_MAX_STRLEN, astr, len_p,
326 				HFS_XATTR_NAME);
327 }
328 EXPORT_SYMBOL_IF_KUNIT(hfsplus_uni2asc_xattr_str);
329 
330 /*
331  * In HFS+, a filename can contain / because : is the separator.
332  * The slash is a valid filename character on macOS.
333  * But on Linux, / is the path separator and
334  * it cannot appear in a filename component.
335  * There's a parallel mapping for the NUL character (0 -> U+2400).
336  * NUL terminates strings in C/POSIX but is valid in HFS+ filenames.
337  */
338 static inline
339 void hfsplus_linux2mac_compatibility_check(wchar_t *uc, int name_type)
340 {
341 	switch (name_type) {
342 	case HFS_XATTR_NAME:
343 		/* ignore conversion */
344 		return;
345 
346 	default:
347 		/* continue logic */
348 		break;
349 	}
350 
351 	switch (*uc) {
352 	case 0x2400:
353 		*uc = 0;
354 		break;
355 	case ':':
356 		*uc = '/';
357 		break;
358 	}
359 }
360 
361 /*
362  * Convert one or more ASCII characters into a single unicode character.
363  * Returns the number of ASCII characters corresponding to the unicode char.
364  */
365 static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
366 			      wchar_t *uc, int name_type)
367 {
368 	int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc);
369 
370 	if (size <= 0) {
371 		*uc = '?';
372 		size = 1;
373 	}
374 
375 	hfsplus_linux2mac_compatibility_check(uc, name_type);
376 	return size;
377 }
378 
379 /* Decomposes a non-Hangul unicode character. */
380 static u16 *hfsplus_decompose_nonhangul(wchar_t uc, int *size)
381 {
382 	int off;
383 
384 	off = hfsplus_decompose_table[(uc >> 12) & 0xf];
385 	if (off == 0 || off == 0xffff)
386 		return NULL;
387 
388 	off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
389 	if (!off)
390 		return NULL;
391 
392 	off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
393 	if (!off)
394 		return NULL;
395 
396 	off = hfsplus_decompose_table[off + (uc & 0xf)];
397 	*size = off & 3;
398 	if (*size == 0)
399 		return NULL;
400 	return hfsplus_decompose_table + (off / 4);
401 }
402 
403 /*
404  * Try to decompose a unicode character as Hangul. Return 0 if @uc is not
405  * precomposed Hangul, otherwise return the length of the decomposition.
406  *
407  * This function was adapted from sample code from the Unicode Standard
408  * Annex #15: Unicode Normalization Forms, version 3.2.0.
409  *
410  * Copyright (C) 1991-2018 Unicode, Inc.  All rights reserved.  Distributed
411  * under the Terms of Use in http://www.unicode.org/copyright.html.
412  */
413 static int hfsplus_try_decompose_hangul(wchar_t uc, u16 *result)
414 {
415 	int index;
416 	int l, v, t;
417 
418 	index = uc - Hangul_SBase;
419 	if (index < 0 || index >= Hangul_SCount)
420 		return 0;
421 
422 	l = Hangul_LBase + index / Hangul_NCount;
423 	v = Hangul_VBase + (index % Hangul_NCount) / Hangul_TCount;
424 	t = Hangul_TBase + index % Hangul_TCount;
425 
426 	result[0] = l;
427 	result[1] = v;
428 	if (t != Hangul_TBase) {
429 		result[2] = t;
430 		return 3;
431 	}
432 	return 2;
433 }
434 
435 /* Decomposes a single unicode character. */
436 static u16 *decompose_unichar(wchar_t uc, int *size, u16 *hangul_buffer)
437 {
438 	u16 *result;
439 
440 	/* Hangul is handled separately */
441 	result = hangul_buffer;
442 	*size = hfsplus_try_decompose_hangul(uc, result);
443 	if (*size == 0)
444 		result = hfsplus_decompose_nonhangul(uc, size);
445 	if (!result) {
446 		/*
447 		 * Not every character with a canonical decomposition is in
448 		 * Apple Technote #1150's own table above; a small, fixed
449 		 * set was only added to the decomposition standard (or had
450 		 * its decomposition corrected) after that table was
451 		 * generated. hfsplus_legacy_decompose() covers those.
452 		 */
453 		const u16 *legacy = hfsplus_legacy_decompose(uc, size);
454 
455 		if (legacy)
456 			result = memcpy(hangul_buffer, legacy,
457 					*size * sizeof(*legacy));
458 	}
459 	return result;
460 }
461 
462 /*
463  * Apply the Unicode Canonical Ordering Algorithm to a decomposed name held
464  * as plain host-order code units: within each maximal run of characters
465  * that have a nonzero combining class, stable-sort the run into ascending
466  * combining-class order. A character with combining class 0 always starts
467  * a new run and is never itself reordered.
468  *
469  * hfsplus_decompose_table decomposes each source character on its own; it
470  * says nothing about how the decompositions of two different source
471  * characters should be ordered relative to each other when both produce
472  * combining marks that end up adjacent. Without this pass, such a
473  * sequence can be stored in an order that macOS's own fsck_hfs
474  * (FixDecomps() in CatalogCheck.c) considers illegal, even though every
475  * individual character was decomposed correctly.
476  */
477 static void hfsplus_canonical_reorder(u16 *ustr, int len)
478 {
479 	int i;
480 
481 	for (i = 1; i < len; i++) {
482 		u8 cls = hfsplus_combining_class(ustr[i]);
483 		int j = i;
484 
485 		if (!cls)
486 			continue;
487 
488 		while (j > 0) {
489 			u8 prev_cls = hfsplus_combining_class(ustr[j - 1]);
490 			u16 tmp;
491 
492 			if (!prev_cls || prev_cls <= cls)
493 				break;
494 
495 			tmp = ustr[j];
496 			ustr[j] = ustr[j - 1];
497 			ustr[j - 1] = tmp;
498 			j--;
499 		}
500 	}
501 }
502 
503 #define HFSPLUS_HANGUL_MAX_JAMO		(3)       /* L + V + optional T */
504 
505 static_assert(HFSPLUS_HANGUL_MAX_JAMO >= HFSPLUS_LEGACY_DECOMP_MAX_LEN,
506 		"hangul_buffer must fit the longest legacy decomposition too");
507 
508 /*
509  * Decompose and canonically reorder an entire Linux name, as plain
510  * host-order code units. hfsplus_asc2uni(), hfsplus_hash_dentry() and
511  * hfsplus_compare_dentry() all go through this so that storage, hashing
512  * and comparison always agree on what a given name canonicalizes to.
513  *
514  * @out must hold at least @max_len entries, which must not exceed
515  * HFSPLUS_MAX_STRLEN. Returns the number of code units written. If
516  * @consumed is non-NULL, it is set to the number of input bytes actually
517  * consumed, which is less than @len when @out fills up first.
518  */
519 static int hfsplus_decompose_str(struct super_block *sb, const char *astr,
520 				  int len, int max_len, int name_type,
521 				  u16 *out, int *consumed)
522 {
523 	int decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
524 	const char *start = astr;
525 	int outlen = 0;
526 
527 	while (outlen < max_len && len > 0) {
528 		u16 *dstr;
529 		u16 dhangul[HFSPLUS_HANGUL_MAX_JAMO];
530 		int dsize, size;
531 		wchar_t c;
532 
533 		size = asc2unichar(sb, astr, len, &c, name_type);
534 
535 		dstr = decompose ? decompose_unichar(c, &dsize, dhangul) : NULL;
536 		if (dstr) {
537 			if (outlen + dsize > max_len)
538 				break;
539 			do {
540 				out[outlen++] = *dstr++;
541 			} while (--dsize > 0);
542 		} else {
543 			out[outlen++] = c;
544 		}
545 
546 		astr += size;
547 		len -= size;
548 	}
549 
550 	hfsplus_canonical_reorder(out, outlen);
551 	hfsplus_fixup_legacy_sequences(out, &outlen);
552 	if (consumed)
553 		*consumed = astr - start;
554 	return outlen;
555 }
556 
557 int hfsplus_asc2uni(struct super_block *sb,
558 		    struct hfsplus_unistr *ustr, int max_unistr_len,
559 		    const char *astr, int len, int name_type)
560 {
561 	u16 buf[HFSPLUS_MAX_STRLEN];
562 	int outlen, i, consumed;
563 
564 	if (max_unistr_len > HFSPLUS_MAX_STRLEN)
565 		max_unistr_len = HFSPLUS_MAX_STRLEN;
566 
567 	outlen = hfsplus_decompose_str(sb, astr, len, max_unistr_len,
568 				       name_type, buf, &consumed);
569 	for (i = 0; i < outlen; i++)
570 		ustr->unicode[i] = cpu_to_be16(buf[i]);
571 	ustr->length = cpu_to_be16(outlen);
572 
573 	if (consumed < len)
574 		return -ENAMETOOLONG;
575 	return 0;
576 }
577 EXPORT_SYMBOL_IF_KUNIT(hfsplus_asc2uni);
578 
579 /*
580  * Maximum length of a single maximal run of nonzero-combining-class code
581  * units that hfsplus_decompose_iter_next() below will canonically
582  * reorder. Every code unit with combining class 0 starts a new run, so
583  * this only bounds how many *consecutive* combining marks between two
584  * base characters get sorted - real text, and even deliberately
585  * adversarial "Zalgo" text, essentially never approaches this. Keeping
586  * it small means hfsplus_hash_dentry() and hfsplus_compare_dentry() only
587  * ever need a tiny amount of lookahead state, rather than buffering an
588  * entire (up to 255-unit) name.
589  */
590 #define HFSPLUS_CCC_RUN_MAX 32
591 
592 /*
593  * Iterator that produces the canonically-ordered, decomposed code units
594  * of a Linux name one at a time, without materializing the whole name.
595  * hfsplus_hash_dentry() and hfsplus_compare_dentry() use this so that
596  * hashing and comparison always agree with what hfsplus_asc2uni() would
597  * actually store, while still comparing lazily (stopping at the first
598  * difference) the way this code did before canonical reordering existed.
599  */
600 struct hfsplus_decompose_iter {
601 	struct super_block *sb;
602 	const char *astr;
603 	int len;
604 	int name_type;
605 	int decompose;
606 
607 	u16 run[HFSPLUS_CCC_RUN_MAX];
608 	int run_len;
609 	int run_pos;
610 };
611 
612 static void hfsplus_decompose_iter_init(struct hfsplus_decompose_iter *it,
613 					struct super_block *sb,
614 					const char *astr, int len,
615 					int name_type)
616 {
617 	it->sb = sb;
618 	it->astr = astr;
619 	it->len = len;
620 	it->name_type = name_type;
621 	it->decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
622 	it->run_len = 0;
623 	it->run_pos = 0;
624 }
625 
626 /*
627  * Gather the next maximal run of nonzero-combining-class code units
628  * (starting with whatever character comes next, base or not) and
629  * canonically reorder just that run. A character is only included once
630  * we know the class of the first unit it produces, so decoding it is
631  * speculative until that's decided.
632  */
633 static bool hfsplus_decompose_iter_refill(struct hfsplus_decompose_iter *it)
634 {
635 	it->run_pos = 0;
636 	it->run_len = 0;
637 
638 	while (it->len > 0) {
639 		u16 *dstr;
640 		u16 dhangul[HFSPLUS_HANGUL_MAX_JAMO];
641 		int dsize, size;
642 		wchar_t c;
643 
644 		size = asc2unichar(it->sb, it->astr, it->len, &c,
645 				   it->name_type);
646 
647 		dstr = it->decompose ?
648 			decompose_unichar(c, &dsize, dhangul) : NULL;
649 		if (!dstr) {
650 			dhangul[0] = c;
651 			dstr = dhangul;
652 			dsize = 1;
653 		}
654 
655 		if (it->run_len > 0 && !hfsplus_combining_class(dstr[0]))
656 			break;
657 
658 		if (it->run_len + dsize > HFSPLUS_CCC_RUN_MAX)
659 			break;
660 
661 		it->astr += size;
662 		it->len -= size;
663 
664 		do {
665 			it->run[it->run_len++] = *dstr++;
666 		} while (--dsize > 0);
667 	}
668 
669 	hfsplus_canonical_reorder(it->run, it->run_len);
670 	hfsplus_fixup_legacy_sequences(it->run, &it->run_len);
671 	return it->run_len > 0;
672 }
673 
674 /* Returns the next code unit, or a negative value once @it is exhausted. */
675 static int hfsplus_decompose_iter_next(struct hfsplus_decompose_iter *it)
676 {
677 	if (it->run_pos >= it->run_len && !hfsplus_decompose_iter_refill(it))
678 		return -1;
679 	return it->run[it->run_pos++];
680 }
681 
682 /*
683  * Returns the next code unit that matters for comparison/hashing: folded
684  * if @casefold, with any character folding to 0 ("ignorable") skipped
685  * entirely. Returns a negative value once @it is exhausted.
686  */
687 static int hfsplus_decompose_iter_next_folded(struct hfsplus_decompose_iter *it,
688 					      int casefold)
689 {
690 	int c;
691 
692 	do {
693 		c = hfsplus_decompose_iter_next(it);
694 		if (c < 0)
695 			return -1;
696 		if (casefold)
697 			c = case_fold(c);
698 	} while (casefold && !c);
699 
700 	return c;
701 }
702 
703 /*
704  * Hash a string to an integer as appropriate for the HFS+ filesystem.
705  * Composed unicode characters are decomposed and case-folding is performed
706  * if the appropriate bits are (un)set on the superblock.
707  */
708 int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
709 {
710 	struct super_block *sb = dentry->d_sb;
711 	int casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
712 	struct hfsplus_decompose_iter it;
713 	unsigned long hash;
714 	int c;
715 
716 	hfsplus_decompose_iter_init(&it, sb, str->name, str->len,
717 				    HFS_REGULAR_NAME);
718 
719 	hash = init_name_hash(dentry);
720 	while ((c = hfsplus_decompose_iter_next_folded(&it, casefold)) >= 0)
721 		hash = partial_name_hash(c, hash);
722 	str->hash = end_name_hash(hash);
723 
724 	return 0;
725 }
726 EXPORT_SYMBOL_IF_KUNIT(hfsplus_hash_dentry);
727 
728 /*
729  * Compare strings with HFS+ filename ordering.
730  * Composed unicode characters are decomposed and case-folding is performed
731  * if the appropriate bits are (un)set on the superblock.
732  */
733 int hfsplus_compare_dentry(const struct dentry *dentry,
734 		unsigned int len, const char *str, const struct qstr *name)
735 {
736 	struct super_block *sb = dentry->d_sb;
737 	int casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
738 	struct hfsplus_decompose_iter it1, it2;
739 
740 	hfsplus_decompose_iter_init(&it1, sb, str, len, HFS_REGULAR_NAME);
741 	hfsplus_decompose_iter_init(&it2, sb, name->name, name->len,
742 				    HFS_REGULAR_NAME);
743 
744 	while (1) {
745 		int c1 = hfsplus_decompose_iter_next_folded(&it1, casefold);
746 		int c2 = hfsplus_decompose_iter_next_folded(&it2, casefold);
747 
748 		if (c1 < 0 || c2 < 0)
749 			return c1 == c2 ? 0 : (c1 < 0 ? -1 : 1);
750 		if (c1 != c2)
751 			return c1 < c2 ? -1 : 1;
752 	}
753 }
754 EXPORT_SYMBOL_IF_KUNIT(hfsplus_compare_dentry);
755