Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  linux/fs/hfs/trans.c
0003  *
0004  * Copyright (C) 1995-1997  Paul H. Hargrove
0005  * This file may be distributed under the terms of the GNU General Public License.
0006  *
0007  * This file contains routines for converting between the Macintosh
0008  * character set and various other encodings.  This includes dealing
0009  * with ':' vs. '/' as the path-element separator.
0010  */
0011 
0012 #include <linux/types.h>
0013 #include <linux/nls.h>
0014 
0015 #include "hfs_fs.h"
0016 
0017 /*================ Global functions ================*/
0018 
0019 /*
0020  * hfs_mac2asc()
0021  *
0022  * Given a 'Pascal String' (a string preceded by a length byte) in
0023  * the Macintosh character set produce the corresponding filename using
0024  * the 'trivial' name-mangling scheme, returning the length of the
0025  * mangled filename.  Note that the output string is not NULL
0026  * terminated.
0027  *
0028  * The name-mangling works as follows:
0029  * The character '/', which is illegal in Linux filenames is replaced
0030  * by ':' which never appears in HFS filenames.  All other characters
0031  * are passed unchanged from input to output.
0032  */
0033 int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
0034 {
0035     struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
0036     struct nls_table *nls_io = HFS_SB(sb)->nls_io;
0037     const char *src;
0038     char *dst;
0039     int srclen, dstlen, size;
0040 
0041     src = in->name;
0042     srclen = in->len;
0043     if (srclen > HFS_NAMELEN)
0044         srclen = HFS_NAMELEN;
0045     dst = out;
0046     dstlen = HFS_MAX_NAMELEN;
0047     if (nls_io) {
0048         wchar_t ch;
0049 
0050         while (srclen > 0) {
0051             if (nls_disk) {
0052                 size = nls_disk->char2uni(src, srclen, &ch);
0053                 if (size <= 0) {
0054                     ch = '?';
0055                     size = 1;
0056                 }
0057                 src += size;
0058                 srclen -= size;
0059             } else {
0060                 ch = *src++;
0061                 srclen--;
0062             }
0063             if (ch == '/')
0064                 ch = ':';
0065             size = nls_io->uni2char(ch, dst, dstlen);
0066             if (size < 0) {
0067                 if (size == -ENAMETOOLONG)
0068                     goto out;
0069                 *dst = '?';
0070                 size = 1;
0071             }
0072             dst += size;
0073             dstlen -= size;
0074         }
0075     } else {
0076         char ch;
0077 
0078         while (--srclen >= 0)
0079             *dst++ = (ch = *src++) == '/' ? ':' : ch;
0080     }
0081 out:
0082     return dst - out;
0083 }
0084 
0085 /*
0086  * hfs_asc2mac()
0087  *
0088  * Given an ASCII string (not null-terminated) and its length,
0089  * generate the corresponding filename in the Macintosh character set
0090  * using the 'trivial' name-mangling scheme, returning the length of
0091  * the mangled filename.  Note that the output string is not NULL
0092  * terminated.
0093  *
0094  * This routine is a inverse to hfs_mac2triv().
0095  * A ':' is replaced by a '/'.
0096  */
0097 void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, const struct qstr *in)
0098 {
0099     struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
0100     struct nls_table *nls_io = HFS_SB(sb)->nls_io;
0101     const char *src;
0102     char *dst;
0103     int srclen, dstlen, size;
0104 
0105     src = in->name;
0106     srclen = in->len;
0107     dst = out->name;
0108     dstlen = HFS_NAMELEN;
0109     if (nls_io) {
0110         wchar_t ch;
0111 
0112         while (srclen > 0) {
0113             size = nls_io->char2uni(src, srclen, &ch);
0114             if (size < 0) {
0115                 ch = '?';
0116                 size = 1;
0117             }
0118             src += size;
0119             srclen -= size;
0120             if (ch == ':')
0121                 ch = '/';
0122             if (nls_disk) {
0123                 size = nls_disk->uni2char(ch, dst, dstlen);
0124                 if (size < 0) {
0125                     if (size == -ENAMETOOLONG)
0126                         goto out;
0127                     *dst = '?';
0128                     size = 1;
0129                 }
0130                 dst += size;
0131                 dstlen -= size;
0132             } else {
0133                 *dst++ = ch > 0xff ? '?' : ch;
0134                 dstlen--;
0135             }
0136         }
0137     } else {
0138         char ch;
0139 
0140         if (dstlen > srclen)
0141             dstlen = srclen;
0142         while (--dstlen >= 0)
0143             *dst++ = (ch = *src++) == ':' ? '/' : ch;
0144     }
0145 out:
0146     out->len = dst - (char *)out->name;
0147     dstlen = HFS_NAMELEN - out->len;
0148     while (--dstlen >= 0)
0149         *dst++ = 0;
0150 }