diff options
Diffstat (limited to 'fs/hfs/trans.c')
| -rw-r--r-- | fs/hfs/trans.c | 116 |
1 files changed, 96 insertions, 20 deletions
diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c index fb9720abbadd..e673a88b8ae7 100644 --- a/fs/hfs/trans.c +++ b/fs/hfs/trans.c | |||
| @@ -9,12 +9,15 @@ | |||
| 9 | * with ':' vs. '/' as the path-element separator. | 9 | * with ':' vs. '/' as the path-element separator. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/types.h> | ||
| 13 | #include <linux/nls.h> | ||
| 14 | |||
| 12 | #include "hfs_fs.h" | 15 | #include "hfs_fs.h" |
| 13 | 16 | ||
| 14 | /*================ Global functions ================*/ | 17 | /*================ Global functions ================*/ |
| 15 | 18 | ||
| 16 | /* | 19 | /* |
| 17 | * hfs_mac2triv() | 20 | * hfs_mac2asc() |
| 18 | * | 21 | * |
| 19 | * Given a 'Pascal String' (a string preceded by a length byte) in | 22 | * Given a 'Pascal String' (a string preceded by a length byte) in |
| 20 | * the Macintosh character set produce the corresponding filename using | 23 | * the Macintosh character set produce the corresponding filename using |
| @@ -27,23 +30,58 @@ | |||
| 27 | * by ':' which never appears in HFS filenames. All other characters | 30 | * by ':' which never appears in HFS filenames. All other characters |
| 28 | * are passed unchanged from input to output. | 31 | * are passed unchanged from input to output. |
| 29 | */ | 32 | */ |
| 30 | int hfs_mac2triv(char *out, const struct hfs_name *in) | 33 | int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in) |
| 31 | { | 34 | { |
| 32 | const char *p; | 35 | struct nls_table *nls_disk = HFS_SB(sb)->nls_disk; |
| 33 | char c; | 36 | struct nls_table *nls_io = HFS_SB(sb)->nls_io; |
| 34 | int i, len; | 37 | const char *src; |
| 38 | char *dst; | ||
| 39 | int srclen, dstlen, size; | ||
| 40 | |||
| 41 | src = in->name; | ||
| 42 | srclen = in->len; | ||
| 43 | dst = out; | ||
| 44 | dstlen = HFS_MAX_NAMELEN; | ||
| 45 | if (nls_io) { | ||
| 46 | wchar_t ch; | ||
| 35 | 47 | ||
| 36 | len = in->len; | 48 | while (srclen > 0) { |
| 37 | p = in->name; | 49 | if (nls_disk) { |
| 38 | for (i = 0; i < len; i++) { | 50 | size = nls_disk->char2uni(src, srclen, &ch); |
| 39 | c = *p++; | 51 | if (size <= 0) { |
| 40 | *out++ = c == '/' ? ':' : c; | 52 | ch = '?'; |
| 53 | size = 1; | ||
| 54 | } | ||
| 55 | src += size; | ||
| 56 | srclen -= size; | ||
| 57 | } else { | ||
| 58 | ch = *src++; | ||
| 59 | srclen--; | ||
| 60 | } | ||
| 61 | if (ch == '/') | ||
| 62 | ch = ':'; | ||
| 63 | size = nls_io->uni2char(ch, dst, dstlen); | ||
| 64 | if (size < 0) { | ||
| 65 | if (size == -ENAMETOOLONG) | ||
| 66 | goto out; | ||
| 67 | *dst = '?'; | ||
| 68 | size = 1; | ||
| 69 | } | ||
| 70 | dst += size; | ||
| 71 | dstlen -= size; | ||
| 72 | } | ||
| 73 | } else { | ||
| 74 | char ch; | ||
| 75 | |||
| 76 | while (--srclen >= 0) | ||
| 77 | *dst++ = (ch = *src++) == '/' ? ':' : ch; | ||
| 41 | } | 78 | } |
| 42 | return i; | 79 | out: |
| 80 | return dst - out; | ||
| 43 | } | 81 | } |
| 44 | 82 | ||
| 45 | /* | 83 | /* |
| 46 | * hfs_triv2mac() | 84 | * hfs_asc2mac() |
| 47 | * | 85 | * |
| 48 | * Given an ASCII string (not null-terminated) and its length, | 86 | * Given an ASCII string (not null-terminated) and its length, |
| 49 | * generate the corresponding filename in the Macintosh character set | 87 | * generate the corresponding filename in the Macintosh character set |
| @@ -54,19 +92,57 @@ int hfs_mac2triv(char *out, const struct hfs_name *in) | |||
| 54 | * This routine is a inverse to hfs_mac2triv(). | 92 | * This routine is a inverse to hfs_mac2triv(). |
| 55 | * A ':' is replaced by a '/'. | 93 | * A ':' is replaced by a '/'. |
| 56 | */ | 94 | */ |
| 57 | void hfs_triv2mac(struct hfs_name *out, struct qstr *in) | 95 | void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, struct qstr *in) |
| 58 | { | 96 | { |
| 97 | struct nls_table *nls_disk = HFS_SB(sb)->nls_disk; | ||
| 98 | struct nls_table *nls_io = HFS_SB(sb)->nls_io; | ||
| 59 | const char *src; | 99 | const char *src; |
| 60 | char *dst, c; | 100 | char *dst; |
| 61 | int i, len; | 101 | int srclen, dstlen, size; |
| 62 | 102 | ||
| 63 | out->len = len = min((unsigned int)HFS_NAMELEN, in->len); | ||
| 64 | src = in->name; | 103 | src = in->name; |
| 104 | srclen = in->len; | ||
| 65 | dst = out->name; | 105 | dst = out->name; |
| 66 | for (i = 0; i < len; i++) { | 106 | dstlen = HFS_NAMELEN; |
| 67 | c = *src++; | 107 | if (nls_io) { |
| 68 | *dst++ = c == ':' ? '/' : c; | 108 | wchar_t ch; |
| 109 | |||
| 110 | while (srclen > 0) { | ||
| 111 | size = nls_io->char2uni(src, srclen, &ch); | ||
| 112 | if (size < 0) { | ||
| 113 | ch = '?'; | ||
| 114 | size = 1; | ||
| 115 | } | ||
| 116 | src += size; | ||
| 117 | srclen -= size; | ||
| 118 | if (ch == ':') | ||
| 119 | ch = '/'; | ||
| 120 | if (nls_disk) { | ||
| 121 | size = nls_disk->uni2char(ch, dst, dstlen); | ||
| 122 | if (size < 0) { | ||
| 123 | if (size == -ENAMETOOLONG) | ||
| 124 | goto out; | ||
| 125 | *dst = '?'; | ||
| 126 | size = 1; | ||
| 127 | } | ||
| 128 | dst += size; | ||
| 129 | dstlen -= size; | ||
| 130 | } else { | ||
| 131 | *dst++ = ch > 0xff ? '?' : ch; | ||
| 132 | dstlen--; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } else { | ||
| 136 | char ch; | ||
| 137 | |||
| 138 | if (dstlen > srclen) | ||
| 139 | dstlen = srclen; | ||
| 140 | while (--dstlen >= 0) | ||
| 141 | *dst++ = (ch = *src++) == ':' ? '/' : ch; | ||
| 69 | } | 142 | } |
| 70 | for (; i < HFS_NAMELEN; i++) | 143 | out: |
| 144 | out->len = dst - (char *)out->name; | ||
| 145 | dstlen = HFS_NAMELEN - out->len; | ||
| 146 | while (--dstlen >= 0) | ||
| 71 | *dst++ = 0; | 147 | *dst++ = 0; |
| 72 | } | 148 | } |
