linux/fs/hfs/trans.c
<<
>>
Prefs
   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        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        }
  81out:
  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 */
  97void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, 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) {
 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        }
 145out:
 146        out->len = dst - (char *)out->name;
 147        dstlen = HFS_NAMELEN - out->len;
 148        while (--dstlen >= 0)
 149                *dst++ = 0;
 150}
 151