2 * Copyright (c) 2000-2013 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <sys/errno.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <sys/utfconv.h>
40 #include <kern/host.h>
41 #include <mach/host_priv.h>
42 #include <libkern/OSKextLib.h>
43 #include <libkern/OSKextLibPrivate.h>
48 lck_grp_t
* encodinglst_lck_grp
;
49 lck_grp_attr_t
* encodinglst_lck_grp_attr
;
50 lck_attr_t
* encodinglst_lck_attr
;
53 /* hfs encoding converter list */
54 SLIST_HEAD(encodinglst
, hfs_encoding
) hfs_encoding_list
= {0};
56 lck_mtx_t encodinglst_mutex
;
58 /* hfs encoding converter entry */
60 SLIST_ENTRY(hfs_encoding
) link
;
64 hfs_to_unicode_func_t get_unicode_func
;
65 unicode_to_hfs_func_t get_hfsname_func
;
68 #define MAX_HFS_UNICODE_CHARS (15*5)
71 static int unicode_to_mac_roman(UniChar
*uni_str
, u_int32_t unicodeChars
, Str31 hfs_str
);
75 hfs_converterinit(void)
77 SLIST_INIT(&hfs_encoding_list
);
79 encodinglst_lck_grp_attr
= lck_grp_attr_alloc_init();
80 encodinglst_lck_grp
= lck_grp_alloc_init("cnode_hash", encodinglst_lck_grp_attr
);
81 encodinglst_lck_attr
= lck_attr_alloc_init();
83 lck_mtx_init(&encodinglst_mutex
, encodinglst_lck_grp
, encodinglst_lck_attr
);
87 * add resident MacRoman converter and take a reference
88 * since its always "loaded". MacRoman is the default converter
89 * for HFS standard volumes.
91 * Only do this if we are actually supporting HFS standard
92 * volumes. The converter is not used on configurations
93 * that do not support HFS standard.
95 hfs_addconverter(0, kTextEncodingMacRoman
, mac_roman_to_unicode
, unicode_to_mac_roman
);
96 SLIST_FIRST(&hfs_encoding_list
)->refcount
++;
104 * Function stubs are needed for KPI export.
105 * It is a little swizzly to have two separate copies of the stub functions in this file
106 * but the prototypes of these functions are different if we're using the real headers
107 * vs. the dummy prototypes at the end of the file. (hfs_to_unicode_func_t vs. void*)
109 * As a result, we need our own copies in the no-HFS-Standard configuration
111 int hfs_addconverter( __unused
int id
,
112 __unused u_int32_t encoding
,
113 __unused hfs_to_unicode_func_t get_unicode
,
114 __unused unicode_to_hfs_func_t get_hfsname
)
119 int hfs_getconverter( __unused u_int32_t encoding
,
120 __unused hfs_to_unicode_func_t
*get_unicode
,
121 __unused unicode_to_hfs_func_t
*get_hfsname
)
126 int hfs_relconverter(__unused u_int32_t encoding
)
131 int hfs_remconverter(__unused
int id
, __unused u_int32_t encoding
)
139 * For configurations that do support HFS standard, we need all of these..
143 * hfs_addconverter - add an HFS encoding converter
145 * This is called exclusivly by kernel loadable modules
146 * (like HFS_Japanese.kmod) to register hfs encoding
147 * conversion routines.
151 hfs_addconverter(int id
, u_int32_t encoding
, hfs_to_unicode_func_t get_unicode
, unicode_to_hfs_func_t get_hfsname
)
153 struct hfs_encoding
*encp
;
155 MALLOC(encp
, struct hfs_encoding
*, sizeof(struct hfs_encoding
), M_TEMP
, M_WAITOK
);
157 lck_mtx_lock(&encodinglst_mutex
);
159 encp
->link
.sle_next
= NULL
;
161 encp
->encoding
= encoding
;
162 encp
->get_unicode_func
= get_unicode
;
163 encp
->get_hfsname_func
= get_hfsname
;
165 SLIST_INSERT_HEAD(&hfs_encoding_list
, encp
, link
);
167 lck_mtx_unlock(&encodinglst_mutex
);
173 * hfs_remconverter - remove an HFS encoding converter
175 * Can be called by a kernel loadable module's finalize
176 * routine to remove an encoding converter so that the
177 * module (i.e. the code) can be unloaded.
179 * However, in the normal case, the removing and unloading
180 * of these converters is done in hfs_relconverter.
181 * The call is initiated from within the kernel during the unmounting of an hfs voulume.
184 hfs_remconverter(int id
, u_int32_t encoding
)
186 struct hfs_encoding
*encp
;
188 lck_mtx_lock(&encodinglst_mutex
);
189 SLIST_FOREACH(encp
, &hfs_encoding_list
, link
) {
190 if (encp
->encoding
== encoding
&& encp
->kmod_id
== id
) {
193 /* if converter is no longer in use, release it */
194 if (encp
->refcount
<= 0 && encp
->kmod_id
!= 0) {
195 SLIST_REMOVE(&hfs_encoding_list
, encp
, hfs_encoding
, link
);
196 lck_mtx_unlock(&encodinglst_mutex
);
200 lck_mtx_unlock(&encodinglst_mutex
);
201 return (1); /* busy */
206 lck_mtx_unlock(&encodinglst_mutex
);
213 * hfs_getconverter - get HFS encoding converters
215 * Normally called during the mounting of an hfs voulume.
218 hfs_getconverter(u_int32_t encoding
, hfs_to_unicode_func_t
*get_unicode
, unicode_to_hfs_func_t
*get_hfsname
)
220 struct hfs_encoding
*encp
;
223 lck_mtx_lock(&encodinglst_mutex
);
224 SLIST_FOREACH(encp
, &hfs_encoding_list
, link
) {
225 if (encp
->encoding
== encoding
) {
227 *get_unicode
= encp
->get_unicode_func
;
228 *get_hfsname
= encp
->get_hfsname_func
;
233 lck_mtx_unlock(&encodinglst_mutex
);
246 * hfs_relconverter - release interest in an HFS encoding converter
248 * Normally called during the unmounting of an hfs voulume.
251 hfs_relconverter(u_int32_t encoding
)
253 struct hfs_encoding
*encp
;
255 lck_mtx_lock(&encodinglst_mutex
);
256 SLIST_FOREACH(encp
, &hfs_encoding_list
, link
) {
257 if (encp
->encoding
== encoding
) {
260 /* if converter is no longer in use, release it */
261 if (encp
->refcount
<= 0 && encp
->kmod_id
!= 0) {
262 uint32_t loadTag
= (uint32_t)encp
->kmod_id
;
264 SLIST_REMOVE(&hfs_encoding_list
, encp
, hfs_encoding
, link
);
265 lck_mtx_unlock(&encodinglst_mutex
);
268 (void)OSKextUnloadKextWithLoadTag(loadTag
);
271 lck_mtx_unlock(&encodinglst_mutex
);
275 lck_mtx_unlock(&encodinglst_mutex
);
281 * Convert HFS encoded string into UTF-8
283 * Unicode output is fully decomposed
284 * '/' chars are converted to ':'
287 hfs_to_utf8(ExtendedVCB
*vcb
, const Str31 hfs_str
, ByteCount maxDstLen
, ByteCount
*actualDstLen
, unsigned char* dstStr
)
290 UniChar uniStr
[MAX_HFS_UNICODE_CHARS
];
293 hfs_to_unicode_func_t hfs_get_unicode
= VCBTOHFS(vcb
)->hfs_get_unicode
;
294 u_int8_t pascal_length
= 0;
297 * Validate the length of the Pascal-style string before passing it
298 * down to the decoding engine.
300 pascal_length
= *((const u_int8_t
*)(hfs_str
));
301 if (pascal_length
> 31) {
302 /* invalid string; longer than 31 bytes */
307 error
= hfs_get_unicode(hfs_str
, uniStr
, MAX_HFS_UNICODE_CHARS
, &uniCount
);
313 error
= utf8_encodestr(uniStr
, uniCount
* sizeof(UniChar
), dstStr
, &utf8len
, maxDstLen
, ':', 0);
314 if (error
== ENAMETOOLONG
)
315 *actualDstLen
= utf8_encodelen(uniStr
, uniCount
* sizeof(UniChar
), ':', 0);
317 *actualDstLen
= utf8len
;
324 * When an HFS name cannot be encoded with the current
325 * volume encoding then MacRoman is used as a fallback.
328 mac_roman_to_utf8(const Str31 hfs_str
, ByteCount maxDstLen
, ByteCount
*actualDstLen
, unsigned char* dstStr
)
331 UniChar uniStr
[MAX_HFS_UNICODE_CHARS
];
334 u_int8_t pascal_length
= 0;
337 * Validate the length of the Pascal-style string before passing it
338 * down to the decoding engine.
340 pascal_length
= *((const u_int8_t
*)(hfs_str
));
341 if (pascal_length
> 31) {
342 /* invalid string; longer than 31 bytes */
347 error
= mac_roman_to_unicode(hfs_str
, uniStr
, MAX_HFS_UNICODE_CHARS
, &uniCount
);
353 error
= utf8_encodestr(uniStr
, uniCount
* sizeof(UniChar
), dstStr
, &utf8len
, maxDstLen
, ':', 0);
354 if (error
== ENAMETOOLONG
)
355 *actualDstLen
= utf8_encodelen(uniStr
, uniCount
* sizeof(UniChar
), ':', 0);
357 *actualDstLen
= utf8len
;
364 * Convert Unicode string into HFS encoding
366 * ':' chars are converted to '/'
367 * Assumes input represents fully decomposed Unicode
370 unicode_to_hfs(ExtendedVCB
*vcb
, ByteCount srcLen
, u_int16_t
* srcStr
, Str31 dstStr
, int retry
)
373 unicode_to_hfs_func_t hfs_get_hfsname
= VCBTOHFS(vcb
)->hfs_get_hfsname
;
375 error
= hfs_get_hfsname(srcStr
, srcLen
/sizeof(UniChar
), dstStr
);
376 if (error
&& retry
) {
377 error
= unicode_to_mac_roman(srcStr
, srcLen
/sizeof(UniChar
), dstStr
);
383 * Convert UTF-8 string into HFS encoding
385 * ':' chars are converted to '/'
386 * Assumes input represents fully decomposed Unicode
389 utf8_to_hfs(ExtendedVCB
*vcb
, ByteCount srcLen
, const unsigned char* srcStr
, Str31 dstStr
/*, int retry*/)
392 UniChar uniStr
[MAX_HFS_UNICODE_CHARS
];
395 error
= utf8_decodestr(srcStr
, srcLen
, uniStr
, &ucslen
, sizeof(uniStr
), ':', 0);
397 error
= unicode_to_hfs(vcb
, ucslen
, uniStr
, dstStr
, 1);
404 utf8_to_mac_roman(ByteCount srcLen
, const unsigned char* srcStr
, Str31 dstStr
)
407 UniChar uniStr
[MAX_HFS_UNICODE_CHARS
];
410 error
= utf8_decodestr(srcStr
, srcLen
, uniStr
, &ucslen
, sizeof(uniStr
), ':', 0);
412 error
= unicode_to_mac_roman(uniStr
, ucslen
/sizeof(UniChar
), dstStr
);
418 * HFS MacRoman to/from Unicode conversions are built into the kernel
419 * All others hfs encodings are loadable.
422 /* 0x00A0 - 0x00FF = Latin 1 Supplement (30 total) */
423 static u_int8_t gLatin1Table
[] = {
424 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
425 /* 0x00A0 */ 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, '?', 0xA4, 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, '?', 0xA8, 0xF8,
426 /* 0x00B0 */ 0xA1, 0XB1, '?', '?', 0xAB, 0xB5, 0xA6, 0xe1, 0xFC, '?', 0xBC, 0xC8, '?', '?', '?', 0xC0,
427 /* 0x00C0 */ '?', '?', '?', '?', '?', '?', 0xAE, '?', '?', '?', '?', '?', '?', '?', '?', '?',
428 /* 0x00D0 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xAF, '?', '?', '?', '?', '?', '?', 0xA7,
429 /* 0x00E0 */ '?', '?', '?', '?', '?', '?', 0xBE, '?', '?', '?', '?', '?', '?', '?', '?', '?',
430 /* 0x00F0 */ '?', '?', '?', '?', '?', '?', '?', 0xD6, 0xBF, '?', '?', '?', '?', '?', '?', '?'
433 /* 0x02C0 - 0x02DF = Spacing Modifiers (8 total) */
434 static u_int8_t gSpaceModsTable
[] = {
435 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
436 /* 0x02C0 */ '?', '?', '?', '?', '?', '?', 0xF6, 0xFF, '?', '?', '?', '?', '?', '?', '?', '?',
437 /* 0x02D0 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xF9, 0xFA, 0xFB, 0xFE, 0xF7, 0xFD, '?', '?'
440 /* 0x2010 - 0x20AF = General Punctuation (17 total) */
441 static u_int8_t gPunctTable
[] = {
442 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
443 /* 0x2010 */ '?', '?', '?', 0xd0, 0xd1, '?', '?', '?', 0xd4, 0xd5, 0xe2, '?', 0xd2, 0xd3, 0xe3, '?',
444 /* 0x2020 */ 0xa0, 0xe0, 0xa5, '?', '?', '?', 0xc9, '?', '?', '?', '?', '?', '?', '?', '?', '?',
445 /* 0x2030 */ 0xe4, '?', '?', '?', '?', '?', '?', '?', '?', 0xdc, 0xdd, '?', '?', '?', '?', '?',
446 /* 0x2040 */ '?', '?', '?', '?', 0xda, '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
447 /* 0x2050 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
448 /* 0x2060 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
449 /* 0x2070 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
450 /* 0x2080 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
451 /* 0x2090 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
452 /* 0x20A0 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 0xdb, '?', '?', '?'
455 /* 0x22xx = Mathematical Operators (11 total) */
456 static u_int8_t gMathTable
[] = {
457 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
458 /* 0x2200 */ '?', '?', 0xb6, '?', '?', '?', 0xc6, '?', '?', '?', '?', '?', '?', '?', '?', 0xb8,
459 /* 0x2210 */ '?', 0xb7, '?', '?', '?', '?', '?', '?', '?', '?', 0xc3, '?', '?', '?', 0xb0, '?',
460 /* 0x2220 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', 0xba, '?', '?', '?', '?',
461 /* 0x2230 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
462 /* 0x2240 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xc5, '?', '?', '?', '?', '?', '?', '?',
463 /* 0x2250 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
464 /* 0x2260 */ 0xad, '?', '?', '?', 0xb2, 0xb3, '?', '?'
468 static u_int8_t gReverseCombTable
[] = {
469 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
470 /* 0x40 */ 0xDA, 0x40, 0xDA, 0xDA, 0xDA, 0x56, 0xDA, 0xDA, 0xDA, 0x6C, 0xDA, 0xDA, 0xDA, 0xDA, 0x82, 0x98,
471 /* 0x50 */ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xAE, 0xDA, 0xDA, 0xDA, 0xC4, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
472 /* 0x60 */ 0xDA, 0x4B, 0xDA, 0xDA, 0xDA, 0x61, 0xDA, 0xDA, 0xDA, 0x77, 0xDA, 0xDA, 0xDA, 0xDA, 0x8D, 0xA3,
473 /* 0x70 */ 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xB9, 0xDA, 0xDA, 0xDA, 0xCF, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
475 /* Combining Diacritical Marks (0x0300 - 0x030A) */
476 /* 0 1 2 3 4 5 6 7 8 9 A */
478 /* 0x0300 */ 0xCB, 0xE7, 0xE5, 0xCC, '?', '?', '?', '?', 0x80, '?', 0x81,
481 /* 0x0300 */ 0x88, 0x87, 0x89, 0x8B, '?', '?', '?', '?', 0x8A, '?', 0x8C,
484 /* 0x0300 */ 0xE9, 0x83, 0xE6, '?', '?', '?', '?', '?', 0xE8, '?', '?',
487 /* 0x0300 */ 0x8F, 0x8E, 0x90, '?', '?', '?', '?', '?', 0x91, '?', '?',
490 /* 0x0300 */ 0xED, 0xEA, 0xEB, '?', '?', '?', '?', '?', 0xEC, '?', '?',
493 /* 0x0300 */ 0x93, 0x92, 0x94, '?', '?', '?', '?', '?', 0x95, '?', '?',
496 /* 0x0300 */ '?', '?', '?', 0x84, '?', '?', '?', '?', '?', '?', '?',
499 /* 0x0300 */ '?', '?', '?', 0x96, '?', '?', '?', '?', '?', '?', '?',
502 /* 0x0300 */ 0xF1, 0xEE, 0xEF, 0xCD, '?', '?', '?', '?', 0x85, '?', '?',
505 /* 0x0300 */ 0x98, 0x97, 0x99, 0x9B, '?', '?', '?', '?', 0x9A, '?', '?',
508 /* 0x0300 */ 0xF4, 0xF2, 0xF3, '?', '?', '?', '?', '?', 0x86, '?', '?',
511 /* 0x0300 */ 0x9D, 0x9C, 0x9E, '?', '?', '?', '?', '?', 0x9F, '?', '?',
514 /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xD9, '?', '?',
517 /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', 0xD8, '?', '?',
520 /* 0x0300 */ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?'
525 * Convert Unicode string into HFS MacRoman encoding
527 * Assumes Unicode input is fully decomposed
529 static int unicode_to_mac_roman(UniChar
*uni_str
, u_int32_t unicodeChars
, Str31 hfs_str
)
535 u_int16_t inputChars
;
536 u_int16_t pascalChars
;
537 OSErr result
= noErr
;
542 mask
= (UniChar
) 0xFF80;
545 inputChars
= unicodeChars
;
546 pascalChars
= prevChar
= 0;
553 * If its not 7-bit ascii, then we need to map it
557 switch (c
& 0xFF00) {
560 mc
= gLatin1Table
[lsb
- 0xA0];
564 if (lsb
>= 0xC0 && lsb
<= 0xDF)
565 mc
= gSpaceModsTable
[lsb
- 0xC0];
569 if (lsb
>= 0x10 && lsb
<= 0xAF)
570 mc
= gPunctTable
[lsb
- 0x10];
575 mc
= gMathTable
[lsb
];
580 if (prevChar
>= 'A' && prevChar
< 'z') {
581 mc
= gReverseCombTable
[gReverseCombTable
[prevChar
- 0x40] + lsb
];
582 --p
; /* backup over base char */
587 case 0x0327: /* combining cedilla */
590 else if (prevChar
== 'c')
594 --p
; /* backup over base char */
598 case 0x03A9: mc
= 0xBD; break; /* omega */
600 case 0x03C0: mc
= 0xB9; break; /* pi */
607 case 0x0131: mc
= 0xf5; break; /* dotless i */
609 case 0x0152: mc
= 0xce; break; /* OE */
611 case 0x0153: mc
= 0xcf; break; /* oe */
613 case 0x0192: mc
= 0xc4; break; /* Ä */
615 case 0x2122: mc
= 0xaa; break; /* TM */
617 case 0x25ca: mc
= 0xd7; break; /* diamond */
619 case 0xf8ff: mc
= 0xf0; break; /* apple logo */
621 case 0xfb01: mc
= 0xde; break; /* fi */
623 case 0xfb02: mc
= 0xdf; break; /* fl */
625 } /* end switch (c & 0xFF00) */
628 * If we have an unmapped character then we need to mangle the name...
631 result
= kTECUsedFallbacksStatus
;
640 if (pascalChars
>= 31)
649 hfs_str
[0] = pascalChars
;
652 result
= ENAMETOOLONG
; /* ran out of room! */
658 static UniChar gHiBitBaseUnicode
[128] = {
659 /* 0x80 */ 0x0041, 0x0041, 0x0043, 0x0045, 0x004e, 0x004f, 0x0055, 0x0061,
660 /* 0x88 */ 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0063, 0x0065, 0x0065,
661 /* 0x90 */ 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, 0x006e, 0x006f,
662 /* 0x98 */ 0x006f, 0x006f, 0x006f, 0x006f, 0x0075, 0x0075, 0x0075, 0x0075,
663 /* 0xa0 */ 0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
664 /* 0xa8 */ 0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
665 /* 0xb0 */ 0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
666 /* 0xb8 */ 0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
667 /* 0xc0 */ 0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
668 /* 0xc8 */ 0x00bb, 0x2026, 0x00a0, 0x0041, 0x0041, 0x004f, 0x0152, 0x0153,
669 /* 0xd0 */ 0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
670 /* 0xd8 */ 0x0079, 0x0059, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
671 /* 0xe0 */ 0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x0041, 0x0045, 0x0041,
672 /* 0xe8 */ 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, 0x004f, 0x004f,
673 /* 0xf0 */ 0xf8ff, 0x004f, 0x0055, 0x0055, 0x0055, 0x0131, 0x02c6, 0x02dc,
674 /* 0xf8 */ 0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
677 static UniChar gHiBitCombUnicode
[128] = {
678 /* 0x80 */ 0x0308, 0x030a, 0x0327, 0x0301, 0x0303, 0x0308, 0x0308, 0x0301,
679 /* 0x88 */ 0x0300, 0x0302, 0x0308, 0x0303, 0x030a, 0x0327, 0x0301, 0x0300,
680 /* 0x90 */ 0x0302, 0x0308, 0x0301, 0x0300, 0x0302, 0x0308, 0x0303, 0x0301,
681 /* 0x98 */ 0x0300, 0x0302, 0x0308, 0x0303, 0x0301, 0x0300, 0x0302, 0x0308,
682 /* 0xa0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
683 /* 0xa8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
684 /* 0xb0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
685 /* 0xb8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
686 /* 0xc0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
687 /* 0xc8 */ 0x0000, 0x0000, 0x0000, 0x0300, 0x0303, 0x0303, 0x0000, 0x0000,
688 /* 0xd0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
689 /* 0xd8 */ 0x0308, 0x0308, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
690 /* 0xe0 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0302, 0x0302, 0x0301,
691 /* 0xe8 */ 0x0308, 0x0300, 0x0301, 0x0302, 0x0308, 0x0300, 0x0301, 0x0302,
692 /* 0xf0 */ 0x0000, 0x0300, 0x0301, 0x0302, 0x0300, 0x0000, 0x0000, 0x0000,
693 /* 0xf8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
698 * Convert HFS MacRoman encoded string into Unicode
700 * Unicode output is fully decomposed
703 mac_roman_to_unicode(const Str31 hfs_str
, UniChar
*uni_str
,
704 __unused u_int32_t maxCharLen
, u_int32_t
*unicodeChars
)
708 u_int16_t pascalChars
;
714 *unicodeChars
= pascalChars
= *(p
++); /* pick up length byte */
716 while (pascalChars
--) {
719 if ( (int8_t) c
>= 0 ) { /* check if seven bit ascii */
720 *(u
++) = (UniChar
) c
; /* just pad high byte with zero */
721 } else { /* its a hi bit character */
725 *(u
++) = uc
= gHiBitBaseUnicode
[c
];
728 * if the unicode character we get back is an alpha char
729 * then we must have an additional combining character
731 if ((uc
<= (UniChar
) 'z') && (uc
>= (UniChar
) 'A')) {
732 *(u
++) = gHiBitCombUnicode
[c
];
741 #endif /* CONFIG_STD_HFS */
746 * These function prototypes are here because hfs.h is not #included
747 * so its prototypes are not provided. These are needed because they are exported
748 * as KPI for the conversion subroutines during mounting of HFS standard.
750 int hfs_addconverter(int id
, u_int32_t encoding
, void * get_unicode
, void * get_hfsname
);
751 int hfs_getconverter(u_int32_t encoding
, void *get_unicode
, void *get_hfsname
);
752 int hfs_relconverter(u_int32_t encoding
);
753 int hfs_remconverter(int id
, u_int32_t encoding
);
755 /* Function stubs are needed for KPI export */
757 int hfs_addconverter( __unused
int id
,
758 __unused u_int32_t encoding
,
759 __unused
void * get_unicode
,
760 __unused
void * get_hfsname
)
765 int hfs_getconverter(__unused u_int32_t encoding
, __unused
void *get_unicode
, __unused
void *get_hfsname
)
770 int hfs_relconverter(__unused u_int32_t encoding
)
775 int hfs_remconverter(__unused
int id
, __unused u_int32_t encoding
)