1 /* 2 * linux/fs/hfs/trans.c 3 * 4 * Copyright (C) 1995-1997 Paul H. Hargrove 5 * This file may be distributed under the terms of the GNU General Public License. 6 * 7 * This file contains routines for converting between the Macintosh 8 * character set and various other encodings. This includes dealing 9 * with ':' vs. '/' as the path-element separator. 10 */ 11 12 #include <linux/types.h> 13 #include <linux/nls.h> 14 15 #include "hfs_fs.h" 16 17 /*================ Global functions ================*/ 18 19 /* 20 * hfs_mac2asc() 21 * 22 * Given a 'Pascal String' (a string preceded by a length byte) in 23 * the Macintosh character set produce the corresponding filename using 24 * the 'trivial' name-mangling scheme, returning the length of the 25 * mangled filename. Note that the output string is not NULL 26 * terminated. 27 * 28 * The name-mangling works as follows: 29 * The character '/', which is illegal in Linux filenames is replaced 30 * by ':' which never appears in HFS filenames. All other characters 31 * are passed unchanged from input to output. 32 */ 33 int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in) 34 { 35 struct nls_table *nls_disk = HFS_SB(sb)->nls_disk; 36 struct nls_table *nls_io = HFS_SB(sb)->nls_io; 37 const char *src; 38 char *dst; 39 int srclen, dstlen, size; 40 41 src = in->name; 42 srclen = in->len; 43 if (srclen > HFS_NAMELEN) 44 srclen = HFS_NAMELEN; 45 dst = out; 46 dstlen = HFS_MAX_NAMELEN; 47 if (nls_io) { 48 wchar_t ch; 49 50 while (srclen > 0) { 51 if (nls_disk) { 52 size = nls_disk->char2uni(src, srclen, &ch); 53 if (size <= 0) { 54 ch = '?'; 55 size = 1; 56 } 57 src += size; 58 srclen -= size; 59 } else { 60 ch = *src++; 61 srclen--; 62 } 63 if (ch == '/') 64 ch = ':'; 65 size = nls_io->uni2char(ch, dst, dstlen); 66 if (size < 0) { 67 if (size == -ENAMETOOLONG) 68 goto out; 69 *dst = '?'; 70 size = 1; 71 } 72 dst += size; 73 dstlen -= size; 74 } 75 } else { 76 char ch; 77 78 while (--srclen >= 0) 79 *dst++ = (ch = *src++) == '/' ? ':' : ch; 80 } 81 out: 82 return dst - out; 83 } 84 85 /* 86 * hfs_asc2mac() 87 * 88 * Given an ASCII string (not null-terminated) and its length, 89 * generate the corresponding filename in the Macintosh character set 90 * using the 'trivial' name-mangling scheme, returning the length of 91 * the mangled filename. Note that the output string is not NULL 92 * terminated. 93 * 94 * This routine is a inverse to hfs_mac2triv(). 95 * A ':' is replaced by a '/'. 96 */ 97 void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, const struct qstr *in) 98 { 99 struct nls_table *nls_disk = HFS_SB(sb)->nls_disk; 100 struct nls_table *nls_io = HFS_SB(sb)->nls_io; 101 const char *src; 102 char *dst; 103 int srclen, dstlen, size; 104 105 src = in->name; 106 srclen = in->len; 107 dst = out->name; 108 dstlen = HFS_NAMELEN; 109 if (nls_io) { 110 wchar_t ch; 111 112 while (srclen > 0 && dstlen > 0) { 113 size = nls_io->char2uni(src, srclen, &ch); 114 if (size < 0) { 115 ch = '?'; 116 size = 1; 117 } 118 src += size; 119 srclen -= size; 120 if (ch == ':') 121 ch = '/'; 122 if (nls_disk) { 123 size = nls_disk->uni2char(ch, dst, dstlen); 124 if (size < 0) { 125 if (size == -ENAMETOOLONG) 126 goto out; 127 *dst = '?'; 128 size = 1; 129 } 130 dst += size; 131 dstlen -= size; 132 } else { 133 *dst++ = ch > 0xff ? '?' : ch; 134 dstlen--; 135 } 136 } 137 } else { 138 char ch; 139 140 if (dstlen > srclen) 141 dstlen = srclen; 142 while (--dstlen >= 0) 143 *dst++ = (ch = *src++) == ':' ? '/' : ch; 144 } 145 out: 146 out->len = dst - (char *)out->name; 147 dstlen = HFS_NAMELEN - out->len; 148 while (--dstlen >= 0) 149 *dst++ = 0; 150 } 151