158f0484fSRodney W. Grimes /*- 27b247341SBaptiste Daroussin * Copyright 2014 Garrett D'Amore <garrett@damore.org> 37b247341SBaptiste Daroussin * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 458f0484fSRodney W. Grimes * Copyright (c) 1993 558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 658f0484fSRodney W. Grimes * 758f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 858f0484fSRodney W. Grimes * Paul Borman at Krystal Technologies. 958f0484fSRodney W. Grimes * 1058f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1158f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1258f0484fSRodney W. Grimes * are met: 1358f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1458f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1558f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1658f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1758f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 1958f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2058f0484fSRodney W. Grimes * without specific prior written permission. 2158f0484fSRodney W. Grimes * 2258f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2358f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2458f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2558f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2658f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2758f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2858f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2958f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3058f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3158f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3258f0484fSRodney W. Grimes * SUCH DAMAGE. 3358f0484fSRodney W. Grimes */ 3458f0484fSRodney W. Grimes 3558f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3658f0484fSRodney W. Grimes static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93"; 3758f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 38333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 39333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4058f0484fSRodney W. Grimes 41d201fe46SDaniel Eischen #include "namespace.h" 42fd8e4ebcSMike Barcroft #include <arpa/inet.h> 4376692b80SAndrey A. Chernov #include <errno.h> 44a0998ce6STim J. Robbins #include <runetype.h> 4558f0484fSRodney W. Grimes #include <stdio.h> 46350a3d3eSAndrey A. Chernov #include <string.h> 4758f0484fSRodney W. Grimes #include <stdlib.h> 48350a3d3eSAndrey A. Chernov #include <sys/types.h> 49350a3d3eSAndrey A. Chernov #include <sys/stat.h> 507b247341SBaptiste Daroussin #include <sys/mman.h> 517b247341SBaptiste Daroussin #include <fcntl.h> 527b247341SBaptiste Daroussin #include <unistd.h> 53d201fe46SDaniel Eischen #include "un-namespace.h" 5458f0484fSRodney W. Grimes 5577bc2a1cSRuslan Bukin #include "endian.h" 56228f8c4fSRuslan Ermilov #include "runefile.h" 57228f8c4fSRuslan Ermilov 58350a3d3eSAndrey A. Chernov _RuneLocale * 597b247341SBaptiste Daroussin _Read_RuneMagi(const char *fname) 60350a3d3eSAndrey A. Chernov { 613fb3a430SRuslan Ermilov char *fdata, *data; 62350a3d3eSAndrey A. Chernov void *lastp; 633fb3a430SRuslan Ermilov _FileRuneLocale *frl; 64350a3d3eSAndrey A. Chernov _RuneLocale *rl; 653fb3a430SRuslan Ermilov _FileRuneEntry *frr; 66350a3d3eSAndrey A. Chernov _RuneEntry *rr; 67350a3d3eSAndrey A. Chernov struct stat sb; 6876692b80SAndrey A. Chernov int x, saverr; 693fb3a430SRuslan Ermilov void *variable; 703fb3a430SRuslan Ermilov _FileRuneEntry *runetype_ext_ranges; 713fb3a430SRuslan Ermilov _FileRuneEntry *maplower_ext_ranges; 723fb3a430SRuslan Ermilov _FileRuneEntry *mapupper_ext_ranges; 733fb3a430SRuslan Ermilov int runetype_ext_len = 0; 747b247341SBaptiste Daroussin int fd; 75350a3d3eSAndrey A. Chernov 767b247341SBaptiste Daroussin if ((fd = _open(fname, O_RDONLY)) < 0) { 777b247341SBaptiste Daroussin errno = EINVAL; 7876692b80SAndrey A. Chernov return (NULL); 797b247341SBaptiste Daroussin } 807b247341SBaptiste Daroussin 817b247341SBaptiste Daroussin if (_fstat(fd, &sb) < 0) { 827b247341SBaptiste Daroussin (void) _close(fd); 837b247341SBaptiste Daroussin errno = EINVAL; 847b247341SBaptiste Daroussin return (NULL); 857b247341SBaptiste Daroussin } 86350a3d3eSAndrey A. Chernov 873fb3a430SRuslan Ermilov if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) { 887b247341SBaptiste Daroussin (void) _close(fd); 897b247341SBaptiste Daroussin errno = EINVAL; 9076692b80SAndrey A. Chernov return (NULL); 9176692b80SAndrey A. Chernov } 92350a3d3eSAndrey A. Chernov 93350a3d3eSAndrey A. Chernov 947b247341SBaptiste Daroussin fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 957b247341SBaptiste Daroussin (void) _close(fd); 967b247341SBaptiste Daroussin if (fdata == NULL) { 977b247341SBaptiste Daroussin errno = EINVAL; 9876692b80SAndrey A. Chernov return (NULL); 9976692b80SAndrey A. Chernov } 100350a3d3eSAndrey A. Chernov 1017b247341SBaptiste Daroussin frl = (_FileRuneLocale *)(void *)fdata; 1023fb3a430SRuslan Ermilov lastp = fdata + sb.st_size; 103350a3d3eSAndrey A. Chernov 1043fb3a430SRuslan Ermilov variable = frl + 1; 105350a3d3eSAndrey A. Chernov 1063fb3a430SRuslan Ermilov if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) { 1077b247341SBaptiste Daroussin goto invalid; 108350a3d3eSAndrey A. Chernov } 109350a3d3eSAndrey A. Chernov 1103fb3a430SRuslan Ermilov runetype_ext_ranges = (_FileRuneEntry *)variable; 11177bc2a1cSRuslan Bukin variable = runetype_ext_ranges + BSWAP(frl->runetype_ext_nranges); 1123fb3a430SRuslan Ermilov if (variable > lastp) { 1137b247341SBaptiste Daroussin goto invalid; 114350a3d3eSAndrey A. Chernov } 115350a3d3eSAndrey A. Chernov 1163fb3a430SRuslan Ermilov maplower_ext_ranges = (_FileRuneEntry *)variable; 11777bc2a1cSRuslan Bukin variable = maplower_ext_ranges + BSWAP(frl->maplower_ext_nranges); 1183fb3a430SRuslan Ermilov if (variable > lastp) { 1197b247341SBaptiste Daroussin goto invalid; 120350a3d3eSAndrey A. Chernov } 121350a3d3eSAndrey A. Chernov 1223fb3a430SRuslan Ermilov mapupper_ext_ranges = (_FileRuneEntry *)variable; 12377bc2a1cSRuslan Bukin variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); 1243fb3a430SRuslan Ermilov if (variable > lastp) { 1257b247341SBaptiste Daroussin goto invalid; 126350a3d3eSAndrey A. Chernov } 127350a3d3eSAndrey A. Chernov 1283fb3a430SRuslan Ermilov frr = runetype_ext_ranges; 12977bc2a1cSRuslan Bukin for (x = 0; x < BSWAP(frl->runetype_ext_nranges); ++x) { 1303fb3a430SRuslan Ermilov uint32_t *types; 131350a3d3eSAndrey A. Chernov 13277bc2a1cSRuslan Bukin if (BSWAP(frr[x].map) == 0) { 13377bc2a1cSRuslan Bukin int len = BSWAP(frr[x].max) - BSWAP(frr[x].min) + 1; 1343fb3a430SRuslan Ermilov types = variable; 1353fb3a430SRuslan Ermilov variable = types + len; 1363fb3a430SRuslan Ermilov runetype_ext_len += len; 1373fb3a430SRuslan Ermilov if (variable > lastp) { 1387b247341SBaptiste Daroussin goto invalid; 139350a3d3eSAndrey A. Chernov } 1403fb3a430SRuslan Ermilov } 141350a3d3eSAndrey A. Chernov } 142350a3d3eSAndrey A. Chernov 14377bc2a1cSRuslan Bukin if ((char *)variable + BSWAP(frl->variable_len) > (char *)lastp) { 1447b247341SBaptiste Daroussin goto invalid; 145350a3d3eSAndrey A. Chernov } 146350a3d3eSAndrey A. Chernov 147350a3d3eSAndrey A. Chernov /* 1483fb3a430SRuslan Ermilov * Convert from disk format to host format. 1493fb3a430SRuslan Ermilov */ 1503fb3a430SRuslan Ermilov data = malloc(sizeof(_RuneLocale) + 15177bc2a1cSRuslan Bukin (BSWAP(frl->runetype_ext_nranges) + BSWAP(frl->maplower_ext_nranges) + 15277bc2a1cSRuslan Bukin BSWAP(frl->mapupper_ext_nranges)) * sizeof(_RuneEntry) + 1533fb3a430SRuslan Ermilov runetype_ext_len * sizeof(*rr->__types) + 15477bc2a1cSRuslan Bukin BSWAP(frl->variable_len)); 1553fb3a430SRuslan Ermilov if (data == NULL) { 1563fb3a430SRuslan Ermilov saverr = errno; 1577b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 1583fb3a430SRuslan Ermilov errno = saverr; 1593fb3a430SRuslan Ermilov return (NULL); 1603fb3a430SRuslan Ermilov } 1613fb3a430SRuslan Ermilov 1623fb3a430SRuslan Ermilov rl = (_RuneLocale *)data; 1633fb3a430SRuslan Ermilov rl->__variable = rl + 1; 1643fb3a430SRuslan Ermilov 1653fb3a430SRuslan Ermilov memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic)); 1663fb3a430SRuslan Ermilov memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); 1673fb3a430SRuslan Ermilov 16877bc2a1cSRuslan Bukin rl->__variable_len = BSWAP(frl->variable_len); 16977bc2a1cSRuslan Bukin rl->__runetype_ext.__nranges = BSWAP(frl->runetype_ext_nranges); 17077bc2a1cSRuslan Bukin rl->__maplower_ext.__nranges = BSWAP(frl->maplower_ext_nranges); 17177bc2a1cSRuslan Bukin rl->__mapupper_ext.__nranges = BSWAP(frl->mapupper_ext_nranges); 1723fb3a430SRuslan Ermilov 1733fb3a430SRuslan Ermilov for (x = 0; x < _CACHED_RUNES; ++x) { 17477bc2a1cSRuslan Bukin rl->__runetype[x] = BSWAP(frl->runetype[x]); 17577bc2a1cSRuslan Bukin rl->__maplower[x] = BSWAP(frl->maplower[x]); 17677bc2a1cSRuslan Bukin rl->__mapupper[x] = BSWAP(frl->mapupper[x]); 1773fb3a430SRuslan Ermilov } 1783fb3a430SRuslan Ermilov 1793fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; 1803fb3a430SRuslan Ermilov rl->__variable = rl->__runetype_ext.__ranges + 1813fb3a430SRuslan Ermilov rl->__runetype_ext.__nranges; 1823fb3a430SRuslan Ermilov 1833fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable; 1843fb3a430SRuslan Ermilov rl->__variable = rl->__maplower_ext.__ranges + 1853fb3a430SRuslan Ermilov rl->__maplower_ext.__nranges; 1863fb3a430SRuslan Ermilov 1873fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable; 1883fb3a430SRuslan Ermilov rl->__variable = rl->__mapupper_ext.__ranges + 1893fb3a430SRuslan Ermilov rl->__mapupper_ext.__nranges; 1903fb3a430SRuslan Ermilov 19177bc2a1cSRuslan Bukin variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); 1923fb3a430SRuslan Ermilov frr = runetype_ext_ranges; 1933fb3a430SRuslan Ermilov rr = rl->__runetype_ext.__ranges; 1943fb3a430SRuslan Ermilov for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { 1953fb3a430SRuslan Ermilov uint32_t *types; 1963fb3a430SRuslan Ermilov 19777bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 19877bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 19977bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2003fb3a430SRuslan Ermilov if (rr[x].__map == 0) { 2013fb3a430SRuslan Ermilov int len = rr[x].__max - rr[x].__min + 1; 2023fb3a430SRuslan Ermilov types = variable; 2033fb3a430SRuslan Ermilov variable = types + len; 2043fb3a430SRuslan Ermilov rr[x].__types = rl->__variable; 2053fb3a430SRuslan Ermilov rl->__variable = rr[x].__types + len; 2063fb3a430SRuslan Ermilov while (len-- > 0) 2073fb3a430SRuslan Ermilov rr[x].__types[len] = types[len]; 2083fb3a430SRuslan Ermilov } else 2093fb3a430SRuslan Ermilov rr[x].__types = NULL; 2103fb3a430SRuslan Ermilov } 2113fb3a430SRuslan Ermilov 2123fb3a430SRuslan Ermilov frr = maplower_ext_ranges; 2133fb3a430SRuslan Ermilov rr = rl->__maplower_ext.__ranges; 2143fb3a430SRuslan Ermilov for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { 21577bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 21677bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 21777bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2183fb3a430SRuslan Ermilov } 2193fb3a430SRuslan Ermilov 2203fb3a430SRuslan Ermilov frr = mapupper_ext_ranges; 2213fb3a430SRuslan Ermilov rr = rl->__mapupper_ext.__ranges; 2223fb3a430SRuslan Ermilov for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { 22377bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 22477bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 22577bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2263fb3a430SRuslan Ermilov } 2273fb3a430SRuslan Ermilov 2283fb3a430SRuslan Ermilov memcpy(rl->__variable, variable, rl->__variable_len); 2297b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 2303fb3a430SRuslan Ermilov 2313fb3a430SRuslan Ermilov /* 232350a3d3eSAndrey A. Chernov * Go out and zero pointers that should be zero. 233350a3d3eSAndrey A. Chernov */ 234ddc1ededSTim J. Robbins if (!rl->__variable_len) 2353fb3a430SRuslan Ermilov rl->__variable = NULL; 236350a3d3eSAndrey A. Chernov 237ddc1ededSTim J. Robbins if (!rl->__runetype_ext.__nranges) 2383fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = NULL; 239350a3d3eSAndrey A. Chernov 240ddc1ededSTim J. Robbins if (!rl->__maplower_ext.__nranges) 2413fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = NULL; 242350a3d3eSAndrey A. Chernov 243ddc1ededSTim J. Robbins if (!rl->__mapupper_ext.__nranges) 2443fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = NULL; 245350a3d3eSAndrey A. Chernov 246350a3d3eSAndrey A. Chernov return (rl); 2477b247341SBaptiste Daroussin 2487b247341SBaptiste Daroussin invalid: 2497b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 2507b247341SBaptiste Daroussin errno = EINVAL; 2517b247341SBaptiste Daroussin return (NULL); 252350a3d3eSAndrey A. Chernov } 253