1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/fs/hfsplus/unicode.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2001
6*4882a593Smuzhiyun * Brad Boyer (flar@allandria.com)
7*4882a593Smuzhiyun * (C) 2003 Ardis Technologies <roman@ardistech.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Handler routines for unicode strings
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/types.h>
13*4882a593Smuzhiyun #include <linux/nls.h>
14*4882a593Smuzhiyun #include "hfsplus_fs.h"
15*4882a593Smuzhiyun #include "hfsplus_raw.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /* Fold the case of a unicode char, given the 16 bit value */
18*4882a593Smuzhiyun /* Returns folded char, or 0 if ignorable */
case_fold(u16 c)19*4882a593Smuzhiyun static inline u16 case_fold(u16 c)
20*4882a593Smuzhiyun {
21*4882a593Smuzhiyun u16 tmp;
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun tmp = hfsplus_case_fold_table[c >> 8];
24*4882a593Smuzhiyun if (tmp)
25*4882a593Smuzhiyun tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
26*4882a593Smuzhiyun else
27*4882a593Smuzhiyun tmp = c;
28*4882a593Smuzhiyun return tmp;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* Compare unicode strings, return values like normal strcmp */
hfsplus_strcasecmp(const struct hfsplus_unistr * s1,const struct hfsplus_unistr * s2)32*4882a593Smuzhiyun int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
33*4882a593Smuzhiyun const struct hfsplus_unistr *s2)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun u16 len1, len2, c1, c2;
36*4882a593Smuzhiyun const hfsplus_unichr *p1, *p2;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun len1 = be16_to_cpu(s1->length);
39*4882a593Smuzhiyun len2 = be16_to_cpu(s2->length);
40*4882a593Smuzhiyun p1 = s1->unicode;
41*4882a593Smuzhiyun p2 = s2->unicode;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun while (1) {
44*4882a593Smuzhiyun c1 = c2 = 0;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun while (len1 && !c1) {
47*4882a593Smuzhiyun c1 = case_fold(be16_to_cpu(*p1));
48*4882a593Smuzhiyun p1++;
49*4882a593Smuzhiyun len1--;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun while (len2 && !c2) {
52*4882a593Smuzhiyun c2 = case_fold(be16_to_cpu(*p2));
53*4882a593Smuzhiyun p2++;
54*4882a593Smuzhiyun len2--;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (c1 != c2)
58*4882a593Smuzhiyun return (c1 < c2) ? -1 : 1;
59*4882a593Smuzhiyun if (!c1 && !c2)
60*4882a593Smuzhiyun return 0;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* Compare names as a sequence of 16-bit unsigned integers */
hfsplus_strcmp(const struct hfsplus_unistr * s1,const struct hfsplus_unistr * s2)65*4882a593Smuzhiyun int hfsplus_strcmp(const struct hfsplus_unistr *s1,
66*4882a593Smuzhiyun const struct hfsplus_unistr *s2)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun u16 len1, len2, c1, c2;
69*4882a593Smuzhiyun const hfsplus_unichr *p1, *p2;
70*4882a593Smuzhiyun int len;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun len1 = be16_to_cpu(s1->length);
73*4882a593Smuzhiyun len2 = be16_to_cpu(s2->length);
74*4882a593Smuzhiyun p1 = s1->unicode;
75*4882a593Smuzhiyun p2 = s2->unicode;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun for (len = min(len1, len2); len > 0; len--) {
78*4882a593Smuzhiyun c1 = be16_to_cpu(*p1);
79*4882a593Smuzhiyun c2 = be16_to_cpu(*p2);
80*4882a593Smuzhiyun if (c1 != c2)
81*4882a593Smuzhiyun return c1 < c2 ? -1 : 1;
82*4882a593Smuzhiyun p1++;
83*4882a593Smuzhiyun p2++;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun return len1 < len2 ? -1 :
87*4882a593Smuzhiyun len1 > len2 ? 1 : 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun #define Hangul_SBase 0xac00
92*4882a593Smuzhiyun #define Hangul_LBase 0x1100
93*4882a593Smuzhiyun #define Hangul_VBase 0x1161
94*4882a593Smuzhiyun #define Hangul_TBase 0x11a7
95*4882a593Smuzhiyun #define Hangul_SCount 11172
96*4882a593Smuzhiyun #define Hangul_LCount 19
97*4882a593Smuzhiyun #define Hangul_VCount 21
98*4882a593Smuzhiyun #define Hangul_TCount 28
99*4882a593Smuzhiyun #define Hangul_NCount (Hangul_VCount * Hangul_TCount)
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun
hfsplus_compose_lookup(u16 * p,u16 cc)102*4882a593Smuzhiyun static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun int i, s, e;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun s = 1;
107*4882a593Smuzhiyun e = p[1];
108*4882a593Smuzhiyun if (!e || cc < p[s * 2] || cc > p[e * 2])
109*4882a593Smuzhiyun return NULL;
110*4882a593Smuzhiyun do {
111*4882a593Smuzhiyun i = (s + e) / 2;
112*4882a593Smuzhiyun if (cc > p[i * 2])
113*4882a593Smuzhiyun s = i + 1;
114*4882a593Smuzhiyun else if (cc < p[i * 2])
115*4882a593Smuzhiyun e = i - 1;
116*4882a593Smuzhiyun else
117*4882a593Smuzhiyun return hfsplus_compose_table + p[i * 2 + 1];
118*4882a593Smuzhiyun } while (s <= e);
119*4882a593Smuzhiyun return NULL;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
hfsplus_uni2asc(struct super_block * sb,const struct hfsplus_unistr * ustr,char * astr,int * len_p)122*4882a593Smuzhiyun int hfsplus_uni2asc(struct super_block *sb,
123*4882a593Smuzhiyun const struct hfsplus_unistr *ustr,
124*4882a593Smuzhiyun char *astr, int *len_p)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun const hfsplus_unichr *ip;
127*4882a593Smuzhiyun struct nls_table *nls = HFSPLUS_SB(sb)->nls;
128*4882a593Smuzhiyun u8 *op;
129*4882a593Smuzhiyun u16 cc, c0, c1;
130*4882a593Smuzhiyun u16 *ce1, *ce2;
131*4882a593Smuzhiyun int i, len, ustrlen, res, compose;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun op = astr;
134*4882a593Smuzhiyun ip = ustr->unicode;
135*4882a593Smuzhiyun ustrlen = be16_to_cpu(ustr->length);
136*4882a593Smuzhiyun len = *len_p;
137*4882a593Smuzhiyun ce1 = NULL;
138*4882a593Smuzhiyun compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun while (ustrlen > 0) {
141*4882a593Smuzhiyun c0 = be16_to_cpu(*ip++);
142*4882a593Smuzhiyun ustrlen--;
143*4882a593Smuzhiyun /* search for single decomposed char */
144*4882a593Smuzhiyun if (likely(compose))
145*4882a593Smuzhiyun ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0);
146*4882a593Smuzhiyun if (ce1)
147*4882a593Smuzhiyun cc = ce1[0];
148*4882a593Smuzhiyun else
149*4882a593Smuzhiyun cc = 0;
150*4882a593Smuzhiyun if (cc) {
151*4882a593Smuzhiyun /* start of a possibly decomposed Hangul char */
152*4882a593Smuzhiyun if (cc != 0xffff)
153*4882a593Smuzhiyun goto done;
154*4882a593Smuzhiyun if (!ustrlen)
155*4882a593Smuzhiyun goto same;
156*4882a593Smuzhiyun c1 = be16_to_cpu(*ip) - Hangul_VBase;
157*4882a593Smuzhiyun if (c1 < Hangul_VCount) {
158*4882a593Smuzhiyun /* compose the Hangul char */
159*4882a593Smuzhiyun cc = (c0 - Hangul_LBase) * Hangul_VCount;
160*4882a593Smuzhiyun cc = (cc + c1) * Hangul_TCount;
161*4882a593Smuzhiyun cc += Hangul_SBase;
162*4882a593Smuzhiyun ip++;
163*4882a593Smuzhiyun ustrlen--;
164*4882a593Smuzhiyun if (!ustrlen)
165*4882a593Smuzhiyun goto done;
166*4882a593Smuzhiyun c1 = be16_to_cpu(*ip) - Hangul_TBase;
167*4882a593Smuzhiyun if (c1 > 0 && c1 < Hangul_TCount) {
168*4882a593Smuzhiyun cc += c1;
169*4882a593Smuzhiyun ip++;
170*4882a593Smuzhiyun ustrlen--;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun goto done;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun while (1) {
176*4882a593Smuzhiyun /* main loop for common case of not composed chars */
177*4882a593Smuzhiyun if (!ustrlen)
178*4882a593Smuzhiyun goto same;
179*4882a593Smuzhiyun c1 = be16_to_cpu(*ip);
180*4882a593Smuzhiyun if (likely(compose))
181*4882a593Smuzhiyun ce1 = hfsplus_compose_lookup(
182*4882a593Smuzhiyun hfsplus_compose_table, c1);
183*4882a593Smuzhiyun if (ce1)
184*4882a593Smuzhiyun break;
185*4882a593Smuzhiyun switch (c0) {
186*4882a593Smuzhiyun case 0:
187*4882a593Smuzhiyun c0 = 0x2400;
188*4882a593Smuzhiyun break;
189*4882a593Smuzhiyun case '/':
190*4882a593Smuzhiyun c0 = ':';
191*4882a593Smuzhiyun break;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun res = nls->uni2char(c0, op, len);
194*4882a593Smuzhiyun if (res < 0) {
195*4882a593Smuzhiyun if (res == -ENAMETOOLONG)
196*4882a593Smuzhiyun goto out;
197*4882a593Smuzhiyun *op = '?';
198*4882a593Smuzhiyun res = 1;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun op += res;
201*4882a593Smuzhiyun len -= res;
202*4882a593Smuzhiyun c0 = c1;
203*4882a593Smuzhiyun ip++;
204*4882a593Smuzhiyun ustrlen--;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun ce2 = hfsplus_compose_lookup(ce1, c0);
207*4882a593Smuzhiyun if (ce2) {
208*4882a593Smuzhiyun i = 1;
209*4882a593Smuzhiyun while (i < ustrlen) {
210*4882a593Smuzhiyun ce1 = hfsplus_compose_lookup(ce2,
211*4882a593Smuzhiyun be16_to_cpu(ip[i]));
212*4882a593Smuzhiyun if (!ce1)
213*4882a593Smuzhiyun break;
214*4882a593Smuzhiyun i++;
215*4882a593Smuzhiyun ce2 = ce1;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun cc = ce2[0];
218*4882a593Smuzhiyun if (cc) {
219*4882a593Smuzhiyun ip += i;
220*4882a593Smuzhiyun ustrlen -= i;
221*4882a593Smuzhiyun goto done;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun same:
225*4882a593Smuzhiyun switch (c0) {
226*4882a593Smuzhiyun case 0:
227*4882a593Smuzhiyun cc = 0x2400;
228*4882a593Smuzhiyun break;
229*4882a593Smuzhiyun case '/':
230*4882a593Smuzhiyun cc = ':';
231*4882a593Smuzhiyun break;
232*4882a593Smuzhiyun default:
233*4882a593Smuzhiyun cc = c0;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun done:
236*4882a593Smuzhiyun res = nls->uni2char(cc, op, len);
237*4882a593Smuzhiyun if (res < 0) {
238*4882a593Smuzhiyun if (res == -ENAMETOOLONG)
239*4882a593Smuzhiyun goto out;
240*4882a593Smuzhiyun *op = '?';
241*4882a593Smuzhiyun res = 1;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun op += res;
244*4882a593Smuzhiyun len -= res;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun res = 0;
247*4882a593Smuzhiyun out:
248*4882a593Smuzhiyun *len_p = (char *)op - astr;
249*4882a593Smuzhiyun return res;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /*
253*4882a593Smuzhiyun * Convert one or more ASCII characters into a single unicode character.
254*4882a593Smuzhiyun * Returns the number of ASCII characters corresponding to the unicode char.
255*4882a593Smuzhiyun */
asc2unichar(struct super_block * sb,const char * astr,int len,wchar_t * uc)256*4882a593Smuzhiyun static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
257*4882a593Smuzhiyun wchar_t *uc)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc);
260*4882a593Smuzhiyun if (size <= 0) {
261*4882a593Smuzhiyun *uc = '?';
262*4882a593Smuzhiyun size = 1;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun switch (*uc) {
265*4882a593Smuzhiyun case 0x2400:
266*4882a593Smuzhiyun *uc = 0;
267*4882a593Smuzhiyun break;
268*4882a593Smuzhiyun case ':':
269*4882a593Smuzhiyun *uc = '/';
270*4882a593Smuzhiyun break;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun return size;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /* Decomposes a non-Hangul unicode character. */
hfsplus_decompose_nonhangul(wchar_t uc,int * size)276*4882a593Smuzhiyun static u16 *hfsplus_decompose_nonhangul(wchar_t uc, int *size)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun int off;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun off = hfsplus_decompose_table[(uc >> 12) & 0xf];
281*4882a593Smuzhiyun if (off == 0 || off == 0xffff)
282*4882a593Smuzhiyun return NULL;
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
285*4882a593Smuzhiyun if (!off)
286*4882a593Smuzhiyun return NULL;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
289*4882a593Smuzhiyun if (!off)
290*4882a593Smuzhiyun return NULL;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun off = hfsplus_decompose_table[off + (uc & 0xf)];
293*4882a593Smuzhiyun *size = off & 3;
294*4882a593Smuzhiyun if (*size == 0)
295*4882a593Smuzhiyun return NULL;
296*4882a593Smuzhiyun return hfsplus_decompose_table + (off / 4);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun /*
300*4882a593Smuzhiyun * Try to decompose a unicode character as Hangul. Return 0 if @uc is not
301*4882a593Smuzhiyun * precomposed Hangul, otherwise return the length of the decomposition.
302*4882a593Smuzhiyun *
303*4882a593Smuzhiyun * This function was adapted from sample code from the Unicode Standard
304*4882a593Smuzhiyun * Annex #15: Unicode Normalization Forms, version 3.2.0.
305*4882a593Smuzhiyun *
306*4882a593Smuzhiyun * Copyright (C) 1991-2018 Unicode, Inc. All rights reserved. Distributed
307*4882a593Smuzhiyun * under the Terms of Use in http://www.unicode.org/copyright.html.
308*4882a593Smuzhiyun */
hfsplus_try_decompose_hangul(wchar_t uc,u16 * result)309*4882a593Smuzhiyun static int hfsplus_try_decompose_hangul(wchar_t uc, u16 *result)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun int index;
312*4882a593Smuzhiyun int l, v, t;
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun index = uc - Hangul_SBase;
315*4882a593Smuzhiyun if (index < 0 || index >= Hangul_SCount)
316*4882a593Smuzhiyun return 0;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun l = Hangul_LBase + index / Hangul_NCount;
319*4882a593Smuzhiyun v = Hangul_VBase + (index % Hangul_NCount) / Hangul_TCount;
320*4882a593Smuzhiyun t = Hangul_TBase + index % Hangul_TCount;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun result[0] = l;
323*4882a593Smuzhiyun result[1] = v;
324*4882a593Smuzhiyun if (t != Hangul_TBase) {
325*4882a593Smuzhiyun result[2] = t;
326*4882a593Smuzhiyun return 3;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun return 2;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun /* Decomposes a single unicode character. */
decompose_unichar(wchar_t uc,int * size,u16 * hangul_buffer)332*4882a593Smuzhiyun static u16 *decompose_unichar(wchar_t uc, int *size, u16 *hangul_buffer)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun u16 *result;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* Hangul is handled separately */
337*4882a593Smuzhiyun result = hangul_buffer;
338*4882a593Smuzhiyun *size = hfsplus_try_decompose_hangul(uc, result);
339*4882a593Smuzhiyun if (*size == 0)
340*4882a593Smuzhiyun result = hfsplus_decompose_nonhangul(uc, size);
341*4882a593Smuzhiyun return result;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
hfsplus_asc2uni(struct super_block * sb,struct hfsplus_unistr * ustr,int max_unistr_len,const char * astr,int len)344*4882a593Smuzhiyun int hfsplus_asc2uni(struct super_block *sb,
345*4882a593Smuzhiyun struct hfsplus_unistr *ustr, int max_unistr_len,
346*4882a593Smuzhiyun const char *astr, int len)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun int size, dsize, decompose;
349*4882a593Smuzhiyun u16 *dstr, outlen = 0;
350*4882a593Smuzhiyun wchar_t c;
351*4882a593Smuzhiyun u16 dhangul[3];
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
354*4882a593Smuzhiyun while (outlen < max_unistr_len && len > 0) {
355*4882a593Smuzhiyun size = asc2unichar(sb, astr, len, &c);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun if (decompose)
358*4882a593Smuzhiyun dstr = decompose_unichar(c, &dsize, dhangul);
359*4882a593Smuzhiyun else
360*4882a593Smuzhiyun dstr = NULL;
361*4882a593Smuzhiyun if (dstr) {
362*4882a593Smuzhiyun if (outlen + dsize > max_unistr_len)
363*4882a593Smuzhiyun break;
364*4882a593Smuzhiyun do {
365*4882a593Smuzhiyun ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
366*4882a593Smuzhiyun } while (--dsize > 0);
367*4882a593Smuzhiyun } else
368*4882a593Smuzhiyun ustr->unicode[outlen++] = cpu_to_be16(c);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun astr += size;
371*4882a593Smuzhiyun len -= size;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun ustr->length = cpu_to_be16(outlen);
374*4882a593Smuzhiyun if (len > 0)
375*4882a593Smuzhiyun return -ENAMETOOLONG;
376*4882a593Smuzhiyun return 0;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun /*
380*4882a593Smuzhiyun * Hash a string to an integer as appropriate for the HFS+ filesystem.
381*4882a593Smuzhiyun * Composed unicode characters are decomposed and case-folding is performed
382*4882a593Smuzhiyun * if the appropriate bits are (un)set on the superblock.
383*4882a593Smuzhiyun */
hfsplus_hash_dentry(const struct dentry * dentry,struct qstr * str)384*4882a593Smuzhiyun int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun struct super_block *sb = dentry->d_sb;
387*4882a593Smuzhiyun const char *astr;
388*4882a593Smuzhiyun const u16 *dstr;
389*4882a593Smuzhiyun int casefold, decompose, size, len;
390*4882a593Smuzhiyun unsigned long hash;
391*4882a593Smuzhiyun wchar_t c;
392*4882a593Smuzhiyun u16 c2;
393*4882a593Smuzhiyun u16 dhangul[3];
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
396*4882a593Smuzhiyun decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
397*4882a593Smuzhiyun hash = init_name_hash(dentry);
398*4882a593Smuzhiyun astr = str->name;
399*4882a593Smuzhiyun len = str->len;
400*4882a593Smuzhiyun while (len > 0) {
401*4882a593Smuzhiyun int dsize;
402*4882a593Smuzhiyun size = asc2unichar(sb, astr, len, &c);
403*4882a593Smuzhiyun astr += size;
404*4882a593Smuzhiyun len -= size;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (decompose)
407*4882a593Smuzhiyun dstr = decompose_unichar(c, &dsize, dhangul);
408*4882a593Smuzhiyun else
409*4882a593Smuzhiyun dstr = NULL;
410*4882a593Smuzhiyun if (dstr) {
411*4882a593Smuzhiyun do {
412*4882a593Smuzhiyun c2 = *dstr++;
413*4882a593Smuzhiyun if (casefold)
414*4882a593Smuzhiyun c2 = case_fold(c2);
415*4882a593Smuzhiyun if (!casefold || c2)
416*4882a593Smuzhiyun hash = partial_name_hash(c2, hash);
417*4882a593Smuzhiyun } while (--dsize > 0);
418*4882a593Smuzhiyun } else {
419*4882a593Smuzhiyun c2 = c;
420*4882a593Smuzhiyun if (casefold)
421*4882a593Smuzhiyun c2 = case_fold(c2);
422*4882a593Smuzhiyun if (!casefold || c2)
423*4882a593Smuzhiyun hash = partial_name_hash(c2, hash);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun str->hash = end_name_hash(hash);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun return 0;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun /*
432*4882a593Smuzhiyun * Compare strings with HFS+ filename ordering.
433*4882a593Smuzhiyun * Composed unicode characters are decomposed and case-folding is performed
434*4882a593Smuzhiyun * if the appropriate bits are (un)set on the superblock.
435*4882a593Smuzhiyun */
hfsplus_compare_dentry(const struct dentry * dentry,unsigned int len,const char * str,const struct qstr * name)436*4882a593Smuzhiyun int hfsplus_compare_dentry(const struct dentry *dentry,
437*4882a593Smuzhiyun unsigned int len, const char *str, const struct qstr *name)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct super_block *sb = dentry->d_sb;
440*4882a593Smuzhiyun int casefold, decompose, size;
441*4882a593Smuzhiyun int dsize1, dsize2, len1, len2;
442*4882a593Smuzhiyun const u16 *dstr1, *dstr2;
443*4882a593Smuzhiyun const char *astr1, *astr2;
444*4882a593Smuzhiyun u16 c1, c2;
445*4882a593Smuzhiyun wchar_t c;
446*4882a593Smuzhiyun u16 dhangul_1[3], dhangul_2[3];
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
449*4882a593Smuzhiyun decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
450*4882a593Smuzhiyun astr1 = str;
451*4882a593Smuzhiyun len1 = len;
452*4882a593Smuzhiyun astr2 = name->name;
453*4882a593Smuzhiyun len2 = name->len;
454*4882a593Smuzhiyun dsize1 = dsize2 = 0;
455*4882a593Smuzhiyun dstr1 = dstr2 = NULL;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun while (len1 > 0 && len2 > 0) {
458*4882a593Smuzhiyun if (!dsize1) {
459*4882a593Smuzhiyun size = asc2unichar(sb, astr1, len1, &c);
460*4882a593Smuzhiyun astr1 += size;
461*4882a593Smuzhiyun len1 -= size;
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun if (decompose)
464*4882a593Smuzhiyun dstr1 = decompose_unichar(c, &dsize1,
465*4882a593Smuzhiyun dhangul_1);
466*4882a593Smuzhiyun if (!decompose || !dstr1) {
467*4882a593Smuzhiyun c1 = c;
468*4882a593Smuzhiyun dstr1 = &c1;
469*4882a593Smuzhiyun dsize1 = 1;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (!dsize2) {
474*4882a593Smuzhiyun size = asc2unichar(sb, astr2, len2, &c);
475*4882a593Smuzhiyun astr2 += size;
476*4882a593Smuzhiyun len2 -= size;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun if (decompose)
479*4882a593Smuzhiyun dstr2 = decompose_unichar(c, &dsize2,
480*4882a593Smuzhiyun dhangul_2);
481*4882a593Smuzhiyun if (!decompose || !dstr2) {
482*4882a593Smuzhiyun c2 = c;
483*4882a593Smuzhiyun dstr2 = &c2;
484*4882a593Smuzhiyun dsize2 = 1;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun c1 = *dstr1;
489*4882a593Smuzhiyun c2 = *dstr2;
490*4882a593Smuzhiyun if (casefold) {
491*4882a593Smuzhiyun c1 = case_fold(c1);
492*4882a593Smuzhiyun if (!c1) {
493*4882a593Smuzhiyun dstr1++;
494*4882a593Smuzhiyun dsize1--;
495*4882a593Smuzhiyun continue;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun c2 = case_fold(c2);
498*4882a593Smuzhiyun if (!c2) {
499*4882a593Smuzhiyun dstr2++;
500*4882a593Smuzhiyun dsize2--;
501*4882a593Smuzhiyun continue;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun if (c1 < c2)
505*4882a593Smuzhiyun return -1;
506*4882a593Smuzhiyun else if (c1 > c2)
507*4882a593Smuzhiyun return 1;
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun dstr1++;
510*4882a593Smuzhiyun dsize1--;
511*4882a593Smuzhiyun dstr2++;
512*4882a593Smuzhiyun dsize2--;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (len1 < len2)
516*4882a593Smuzhiyun return -1;
517*4882a593Smuzhiyun if (len1 > len2)
518*4882a593Smuzhiyun return 1;
519*4882a593Smuzhiyun return 0;
520*4882a593Smuzhiyun }
521