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        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