Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

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