1 /* $NetBSD: src/lib/libc/locale/rune.c,v 1.26 2004/05/09 11:26:33 kleink Exp $ */ 2 /* $DragonFly: src/lib/libc/locale/rune.c,v 1.6 2005/11/20 09:18:37 swildner Exp $ */ 3 4 /*- 5 * Copyright (c)1999 Citrus Project, 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /*- 31 * Copyright (c) 1993 32 * The Regents of the University of California. All rights reserved. 33 * 34 * This code is derived from software contributed to Berkeley by 35 * Paul Borman at Krystal Technologies. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 #include <sys/types.h> 63 #include <sys/stat.h> 64 #include <assert.h> 65 #include <errno.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <wchar.h> 70 71 #include <arpa/inet.h> 72 73 #include "../citrus/citrus_module.h" 74 #include "../citrus/citrus_ctype.h" 75 #include "rune.h" 76 #include "rune_local.h" 77 78 static int readrange(_RuneLocale *, _RuneRange *, _FileRuneRange *, 79 void *, FILE *); 80 static void _freeentry(_RuneRange *); 81 static void _wctype_init(_RuneLocale *rl); 82 83 static int 84 readrange(_RuneLocale *rl, _RuneRange *rr, _FileRuneRange *frr, void *lastp, 85 FILE *fp) 86 { 87 uint32_t i; 88 _RuneEntry *re; 89 _FileRuneEntry fre; 90 91 _DIAGASSERT(rl != NULL); 92 _DIAGASSERT(rr != NULL); 93 _DIAGASSERT(frr != NULL); 94 _DIAGASSERT(lastp != NULL); 95 _DIAGASSERT(fp != NULL); 96 97 re = (_RuneEntry *)rl->rl_variable; 98 99 rr->rr_nranges = ntohl(frr->frr_nranges); 100 if (rr->rr_nranges == 0) { 101 rr->rr_rune_ranges = NULL; 102 return(0); 103 } 104 105 rr->rr_rune_ranges = re; 106 for (i = 0; i < rr->rr_nranges; i++) { 107 if (fread(&fre, sizeof(fre), 1, fp) != 1) 108 return(-1); 109 110 re->re_min = ntohl((uint32_t)fre.fre_min); 111 re->re_max = ntohl((uint32_t)fre.fre_max); 112 re->re_map = ntohl((uint32_t)fre.fre_map); 113 re++; 114 115 if ((void *)re > lastp) 116 return(-1); 117 } 118 rl->rl_variable = re; 119 return(0); 120 } 121 122 static int 123 readentry(_RuneRange *rr, FILE *fp) 124 { 125 _RuneEntry *re; 126 size_t l, i, j; 127 int error; 128 129 _DIAGASSERT(rr != NULL); 130 _DIAGASSERT(fp != NULL); 131 132 re = rr->rr_rune_ranges; 133 for (i = 0; i < rr->rr_nranges; i++) { 134 if (re[i].re_map != 0) { 135 re[i].re_rune_types = NULL; 136 continue; 137 } 138 139 l = re[i].re_max - re[i].re_min + 1; 140 re[i].re_rune_types = malloc(l * sizeof(_RuneType)); 141 if (!re[i].re_rune_types) { 142 error = ENOMEM; 143 goto fail; 144 } 145 memset(re[i].re_rune_types, 0, l * sizeof(_RuneType)); 146 147 if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l) 148 goto fail2; 149 150 for (j = 0; j < l; j++) 151 re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]); 152 } 153 return(0); 154 155 fail: 156 for (j = 0; j < i; j++) { 157 free(re[j].re_rune_types); 158 re[j].re_rune_types = NULL; 159 } 160 return(error); 161 162 fail2: 163 for (j = 0; j <= i; j++) { 164 free(re[j].re_rune_types); 165 re[j].re_rune_types = NULL; 166 } 167 return(errno); 168 } 169 170 /* XXX: temporary implementation */ 171 static void 172 find_codeset(_RuneLocale *rl) 173 { 174 char *top, *codeset, *tail, *ep; 175 176 /* end of rl_variable region */ 177 ep = (char *)rl->rl_variable; 178 ep += rl->rl_variable_len; 179 rl->rl_codeset = NULL; 180 if (!(top = strstr(rl->rl_variable, _RUNE_CODESET))) 181 return; 182 tail = strpbrk(top, " \t"); 183 codeset = top + sizeof(_RUNE_CODESET) - 1; 184 if (tail) { 185 *top = *tail; 186 *tail = '\0'; 187 rl->rl_codeset = strdup(codeset); 188 strlcpy(top + 1, tail + 1, (unsigned)(ep - (top + 1))); 189 } else { 190 *top = '\0'; 191 rl->rl_codeset = strdup(codeset); 192 } 193 } 194 195 static void 196 _freeentry(_RuneRange *rr) 197 { 198 _RuneEntry *re; 199 uint32_t i; 200 201 _DIAGASSERT(rr != NULL); 202 203 re = rr->rr_rune_ranges; 204 for (i = 0; i < rr->rr_nranges; i++) { 205 if (re[i].re_rune_types) 206 free(re[i].re_rune_types); 207 re[i].re_rune_types = NULL; 208 } 209 } 210 211 void 212 _wctype_init(_RuneLocale *rl) 213 { 214 memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype, 215 sizeof(rl->rl_wctype)); 216 } 217 218 219 _RuneLocale * 220 _Read_RuneMagi(FILE *fp) 221 { 222 /* file */ 223 _FileRuneLocale frl; 224 /* host data */ 225 char *hostdata; 226 size_t hostdatalen; 227 void *lastp; 228 _RuneLocale *rl; 229 struct stat sb; 230 int x; 231 232 _DIAGASSERT(fp != NULL); 233 234 if (fstat(fileno(fp), &sb) < 0) 235 return(NULL); 236 237 if (sb.st_size < sizeof(_FileRuneLocale)) 238 return(NULL); 239 /* XXX more validation? */ 240 241 /* Someone might have read the magic number once already */ 242 rewind(fp); 243 244 if (fread(&frl, sizeof(frl), 1, fp) != 1) 245 return(NULL); 246 if (memcmp(frl.frl_magic, _RUNE_MAGIC_1, sizeof(frl.frl_magic))) 247 return(NULL); 248 249 hostdatalen = sizeof(*rl) + ntohl((u_int32_t)frl.frl_variable_len) + 250 ntohl(frl.frl_runetype_ext.frr_nranges) * sizeof(_RuneEntry) + 251 ntohl(frl.frl_maplower_ext.frr_nranges) * sizeof(_RuneEntry) + 252 ntohl(frl.frl_mapupper_ext.frr_nranges) * sizeof(_RuneEntry); 253 254 if ((hostdata = malloc(hostdatalen)) == NULL) 255 return(NULL); 256 memset(hostdata, 0, hostdatalen); 257 lastp = hostdata + hostdatalen; 258 259 rl = (_RuneLocale *)(void *)hostdata; 260 rl->rl_variable = rl + 1; 261 262 memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic)); 263 memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding)); 264 265 rl->rl_invalid_rune = ntohl((u_int32_t)frl.frl_invalid_rune); 266 rl->rl_variable_len = ntohl((u_int32_t)frl.frl_variable_len); 267 268 for (x = 0; x < _CACHED_RUNES; ++x) { 269 rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]); 270 271 /* XXX assumes rune_t = u_int32_t */ 272 rl->rl_maplower[x] = ntohl((uint32_t)frl.frl_maplower[x]); 273 rl->rl_mapupper[x] = ntohl((uint32_t)frl.frl_mapupper[x]); 274 } 275 276 if (readrange(rl, &rl->rl_runetype_ext, &frl.frl_runetype_ext, 277 lastp, fp)) { 278 free(hostdata); 279 return(NULL); 280 } 281 if (readrange(rl, &rl->rl_maplower_ext, &frl.frl_maplower_ext, 282 lastp, fp)) { 283 free(hostdata); 284 return(NULL); 285 } 286 if (readrange(rl, &rl->rl_mapupper_ext, &frl.frl_mapupper_ext, 287 lastp, fp)) { 288 free(hostdata); 289 return(NULL); 290 } 291 292 if (readentry(&rl->rl_runetype_ext, fp) != 0) { 293 free(hostdata); 294 return(NULL); 295 } 296 297 if ((uint8_t *)rl->rl_variable + rl->rl_variable_len > 298 (uint8_t *)lastp) { 299 _freeentry(&rl->rl_runetype_ext); 300 free(hostdata); 301 return(NULL); 302 } 303 if (rl->rl_variable_len == 0) 304 rl->rl_variable = NULL; 305 else if (fread(rl->rl_variable, rl->rl_variable_len, 1, fp) != 1) { 306 _freeentry(&rl->rl_runetype_ext); 307 free(hostdata); 308 return(NULL); 309 } 310 find_codeset(rl); 311 _wctype_init(rl); 312 313 /* error if we have junk at the tail */ 314 if (ftell(fp) != sb.st_size) { 315 _freeentry(&rl->rl_runetype_ext); 316 free(hostdata); 317 return(NULL); 318 } 319 320 return(rl); 321 } 322 323 void 324 _NukeRune(_RuneLocale *rl) 325 { 326 _DIAGASSERT(rl != NULL); 327 328 if (rl != &_DefaultRuneLocale) { 329 _freeentry(&rl->rl_runetype_ext); 330 if (rl->rl_codeset != NULL) 331 free(rl->rl_codeset); 332 if (rl->rl_citrus_ctype) 333 _citrus_ctype_close(rl->rl_citrus_ctype); 334 free(rl); 335 } 336 } 337