1 /* $OpenBSD: ntfs_conv.c,v 1.6 2009/03/25 20:39:47 oga Exp $ */ 2 /* $NetBSD: ntfs_conv.c,v 1.1 2002/12/23 17:38:32 jdolecek Exp $ */ 3 4 /*- 5 * Copyright (c) 2001 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * File name recode stuff. 32 * 33 * The utf-8 routines were derived from src/lib/libc/locale/utf2.c. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/namei.h> 39 #include <sys/proc.h> 40 #include <sys/kernel.h> 41 #include <sys/vnode.h> 42 #include <sys/mount.h> 43 #include <sys/buf.h> 44 #include <sys/file.h> 45 #include <sys/malloc.h> 46 #if defined(__FreeBSD__) 47 #include <machine/clock.h> 48 #endif 49 50 #include <miscfs/specfs/specdev.h> 51 52 /* #define NTFS_DEBUG 1 */ 53 #if defined(__FreeBSD__) || defined(__NetBSD__) 54 #include <fs/ntfs/ntfs.h> 55 #include <fs/ntfs/ntfsmount.h> 56 #include <fs/ntfs/ntfs_inode.h> 57 #include <fs/ntfs/ntfs_vfsops.h> 58 #include <fs/ntfs/ntfs_subr.h> 59 #include <fs/ntfs/ntfs_compr.h> 60 #include <fs/ntfs/ntfs_ihash.h> 61 #else 62 #include <ntfs/ntfs.h> 63 #include <ntfs/ntfsmount.h> 64 #include <ntfs/ntfs_inode.h> 65 #include <ntfs/ntfs_vfsops.h> 66 #include <ntfs/ntfs_subr.h> 67 #include <ntfs/ntfs_compr.h> 68 #include <ntfs/ntfs_ihash.h> 69 #endif 70 71 /* UTF-8 encoding stuff */ 72 73 static const int _utf_count[16] = { 74 1, 1, 1, 1, 1, 1, 1, 1, 75 0, 0, 0, 0, 2, 2, 3, 0, 76 }; 77 78 /* 79 * Read one wide character off the string, shift the string pointer 80 * and return the character. 81 */ 82 wchar 83 ntfs_utf8_wget(const char **str) 84 { 85 int c; 86 wchar rune = 0; 87 const char *s = *str; 88 89 c = _utf_count[(s[0] >> 4) & 0xf]; 90 if (c == 0) { 91 c = 1; 92 goto encoding_error; 93 } 94 95 switch (c) { 96 case 1: 97 rune = s[0] & 0xff; 98 break; 99 case 2: 100 if ((s[1] & 0xc0) != 0x80) 101 goto encoding_error; 102 rune = ((s[0] & 0x1F) << 6) | (s[1] & 0x3F); 103 break; 104 case 3: 105 if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80) 106 goto encoding_error; 107 rune = ((s[0] & 0x1F) << 12) | ((s[1] & 0x3F) << 6) 108 | (s[2] & 0x3F); 109 break; 110 } 111 112 encoding_error: 113 *str = *str + c; 114 return rune; 115 } 116 117 /* 118 * Encode wide character and write it to the string. 'n' specifies 119 * how much space there is in the string. Returns number of bytes written 120 * to the target string. 121 */ 122 int 123 ntfs_utf8_wput(char *s, size_t n, wchar wc) 124 { 125 if (wc & 0xf800) { 126 if (n < 3) { 127 /* bound check failure */ 128 ddprintf(("ntfs_utf8_wput: need 3 bytes\n")); 129 return 0; 130 } 131 132 s[0] = 0xE0 | ((wc >> 12) & 0x0F); 133 s[1] = 0x80 | ((wc >> 6) & 0x3F); 134 s[2] = 0x80 | ((wc) & 0x3F); 135 return 3; 136 } else { 137 if (wc & 0x0780) { 138 if (n < 2) { 139 /* bound check failure */ 140 ddprintf(("ntfs_utf8_wput: need 2 bytes\n")); 141 return 0; 142 } 143 144 s[0] = 0xC0 | ((wc >> 6) & 0x1F); 145 s[1] = 0x80 | ((wc) & 0x3F); 146 return 2; 147 } else { 148 if (n < 1) { 149 /* bound check failure */ 150 ddprintf(("ntfs_utf8_wput: need 1 byte\n")); 151 return 0; 152 } 153 154 s[0] = wc; 155 return 1; 156 } 157 } 158 } 159 160 /* 161 * Compare two wide characters, returning 1, 0, -1 if the first is 162 * bigger, equal or lower than the second. 163 */ 164 int 165 ntfs_utf8_wcmp(wchar wc1, wchar wc2) 166 { 167 /* no conversions needed for utf8 */ 168 169 if (wc1 == wc2) 170 return 0; 171 else 172 return (int) wc1 - (int) wc2; 173 } 174