Root/fs/hfs/trans.c

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 */
33int 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    dst = out;
44    dstlen = HFS_MAX_NAMELEN;
45    if (nls_io) {
46        wchar_t ch;
47
48        while (srclen > 0) {
49            if (nls_disk) {
50                size = nls_disk->char2uni(src, srclen, &ch);
51                if (size <= 0) {
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;
78    }
79out:
80    return dst - out;
81}
82
83/*
84 * hfs_asc2mac()
85 *
86 * Given an ASCII string (not null-terminated) and its length,
87 * generate the corresponding filename in the Macintosh character set
88 * using the 'trivial' name-mangling scheme, returning the length of
89 * the mangled filename. Note that the output string is not NULL
90 * terminated.
91 *
92 * This routine is a inverse to hfs_mac2triv().
93 * A ':' is replaced by a '/'.
94 */
95void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, struct qstr *in)
96{
97    struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
98    struct nls_table *nls_io = HFS_SB(sb)->nls_io;
99    const char *src;
100    char *dst;
101    int srclen, dstlen, size;
102
103    src = in->name;
104    srclen = in->len;
105    dst = out->name;
106    dstlen = HFS_NAMELEN;
107    if (nls_io) {
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;
142    }
143out:
144    out->len = dst - (char *)out->name;
145    dstlen = HFS_NAMELEN - out->len;
146    while (--dstlen >= 0)
147        *dst++ = 0;
148}
149

Archive Download this file



interactive