158f0484fSRodney W. Grimes /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 47b247341SBaptiste Daroussin * Copyright 2014 Garrett D'Amore <garrett@damore.org> 57b247341SBaptiste Daroussin * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 658f0484fSRodney W. Grimes * Copyright (c) 1993 758f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 858f0484fSRodney W. Grimes * 958f0484fSRodney W. Grimes * This code is derived from software contributed to Berkeley by 1058f0484fSRodney W. Grimes * Paul Borman at Krystal Technologies. 1158f0484fSRodney W. Grimes * 1258f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1358f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1458f0484fSRodney W. Grimes * are met: 1558f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1658f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1758f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1858f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1958f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 20fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 2158f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2258f0484fSRodney W. Grimes * without specific prior written permission. 2358f0484fSRodney W. Grimes * 2458f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2558f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2658f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2758f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2858f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2958f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3058f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3158f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3258f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3358f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3458f0484fSRodney W. Grimes * SUCH DAMAGE. 3558f0484fSRodney W. Grimes */ 3658f0484fSRodney W. Grimes 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 3858f0484fSRodney W. Grimes static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93"; 3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 40333fc21eSDavid E. O'Brien #include <sys/cdefs.h> 41333fc21eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 4258f0484fSRodney W. Grimes 43d201fe46SDaniel Eischen #include "namespace.h" 44fd8e4ebcSMike Barcroft #include <arpa/inet.h> 4576692b80SAndrey A. Chernov #include <errno.h> 46a0998ce6STim J. Robbins #include <runetype.h> 4758f0484fSRodney W. Grimes #include <stdio.h> 48350a3d3eSAndrey A. Chernov #include <string.h> 4958f0484fSRodney W. Grimes #include <stdlib.h> 50350a3d3eSAndrey A. Chernov #include <sys/types.h> 51350a3d3eSAndrey A. Chernov #include <sys/stat.h> 527b247341SBaptiste Daroussin #include <sys/mman.h> 537b247341SBaptiste Daroussin #include <fcntl.h> 547b247341SBaptiste Daroussin #include <unistd.h> 55d201fe46SDaniel Eischen #include "un-namespace.h" 5658f0484fSRodney W. Grimes 5777bc2a1cSRuslan Bukin #include "endian.h" 58228f8c4fSRuslan Ermilov #include "runefile.h" 59228f8c4fSRuslan Ermilov 60350a3d3eSAndrey A. Chernov _RuneLocale * 617b247341SBaptiste Daroussin _Read_RuneMagi(const char *fname) 62350a3d3eSAndrey A. Chernov { 633fb3a430SRuslan Ermilov char *fdata, *data; 64350a3d3eSAndrey A. Chernov void *lastp; 653fb3a430SRuslan Ermilov _FileRuneLocale *frl; 66350a3d3eSAndrey A. Chernov _RuneLocale *rl; 673fb3a430SRuslan Ermilov _FileRuneEntry *frr; 68350a3d3eSAndrey A. Chernov _RuneEntry *rr; 69350a3d3eSAndrey A. Chernov struct stat sb; 7076692b80SAndrey A. Chernov int x, saverr; 713fb3a430SRuslan Ermilov void *variable; 723fb3a430SRuslan Ermilov _FileRuneEntry *runetype_ext_ranges; 733fb3a430SRuslan Ermilov _FileRuneEntry *maplower_ext_ranges; 743fb3a430SRuslan Ermilov _FileRuneEntry *mapupper_ext_ranges; 753fb3a430SRuslan Ermilov int runetype_ext_len = 0; 767b247341SBaptiste Daroussin int fd; 77350a3d3eSAndrey A. Chernov 787b247341SBaptiste Daroussin if ((fd = _open(fname, O_RDONLY)) < 0) { 797b247341SBaptiste Daroussin errno = EINVAL; 8076692b80SAndrey A. Chernov return (NULL); 817b247341SBaptiste Daroussin } 827b247341SBaptiste Daroussin 837b247341SBaptiste Daroussin if (_fstat(fd, &sb) < 0) { 847b247341SBaptiste Daroussin (void) _close(fd); 857b247341SBaptiste Daroussin errno = EINVAL; 867b247341SBaptiste Daroussin return (NULL); 877b247341SBaptiste Daroussin } 88350a3d3eSAndrey A. Chernov 893fb3a430SRuslan Ermilov if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) { 907b247341SBaptiste Daroussin (void) _close(fd); 917b247341SBaptiste Daroussin errno = EINVAL; 9276692b80SAndrey A. Chernov return (NULL); 9376692b80SAndrey A. Chernov } 94350a3d3eSAndrey A. Chernov 95350a3d3eSAndrey A. Chernov 967b247341SBaptiste Daroussin fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 977b247341SBaptiste Daroussin (void) _close(fd); 987b247341SBaptiste Daroussin if (fdata == NULL) { 997b247341SBaptiste Daroussin errno = EINVAL; 10076692b80SAndrey A. Chernov return (NULL); 10176692b80SAndrey A. Chernov } 102350a3d3eSAndrey A. Chernov 1037b247341SBaptiste Daroussin frl = (_FileRuneLocale *)(void *)fdata; 1043fb3a430SRuslan Ermilov lastp = fdata + sb.st_size; 105350a3d3eSAndrey A. Chernov 1063fb3a430SRuslan Ermilov variable = frl + 1; 107350a3d3eSAndrey A. Chernov 1083fb3a430SRuslan Ermilov if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) { 1097b247341SBaptiste Daroussin goto invalid; 110350a3d3eSAndrey A. Chernov } 111350a3d3eSAndrey A. Chernov 1123fb3a430SRuslan Ermilov runetype_ext_ranges = (_FileRuneEntry *)variable; 11377bc2a1cSRuslan Bukin variable = runetype_ext_ranges + BSWAP(frl->runetype_ext_nranges); 1143fb3a430SRuslan Ermilov if (variable > lastp) { 1157b247341SBaptiste Daroussin goto invalid; 116350a3d3eSAndrey A. Chernov } 117350a3d3eSAndrey A. Chernov 1183fb3a430SRuslan Ermilov maplower_ext_ranges = (_FileRuneEntry *)variable; 11977bc2a1cSRuslan Bukin variable = maplower_ext_ranges + BSWAP(frl->maplower_ext_nranges); 1203fb3a430SRuslan Ermilov if (variable > lastp) { 1217b247341SBaptiste Daroussin goto invalid; 122350a3d3eSAndrey A. Chernov } 123350a3d3eSAndrey A. Chernov 1243fb3a430SRuslan Ermilov mapupper_ext_ranges = (_FileRuneEntry *)variable; 12577bc2a1cSRuslan Bukin variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); 1263fb3a430SRuslan Ermilov if (variable > lastp) { 1277b247341SBaptiste Daroussin goto invalid; 128350a3d3eSAndrey A. Chernov } 129350a3d3eSAndrey A. Chernov 1303fb3a430SRuslan Ermilov frr = runetype_ext_ranges; 13177bc2a1cSRuslan Bukin for (x = 0; x < BSWAP(frl->runetype_ext_nranges); ++x) { 1323fb3a430SRuslan Ermilov uint32_t *types; 133350a3d3eSAndrey A. Chernov 13477bc2a1cSRuslan Bukin if (BSWAP(frr[x].map) == 0) { 13577bc2a1cSRuslan Bukin int len = BSWAP(frr[x].max) - BSWAP(frr[x].min) + 1; 1363fb3a430SRuslan Ermilov types = variable; 1373fb3a430SRuslan Ermilov variable = types + len; 1383fb3a430SRuslan Ermilov runetype_ext_len += len; 1393fb3a430SRuslan Ermilov if (variable > lastp) { 1407b247341SBaptiste Daroussin goto invalid; 141350a3d3eSAndrey A. Chernov } 1423fb3a430SRuslan Ermilov } 143350a3d3eSAndrey A. Chernov } 144350a3d3eSAndrey A. Chernov 14577bc2a1cSRuslan Bukin if ((char *)variable + BSWAP(frl->variable_len) > (char *)lastp) { 1467b247341SBaptiste Daroussin goto invalid; 147350a3d3eSAndrey A. Chernov } 148350a3d3eSAndrey A. Chernov 149350a3d3eSAndrey A. Chernov /* 1503fb3a430SRuslan Ermilov * Convert from disk format to host format. 1513fb3a430SRuslan Ermilov */ 1523fb3a430SRuslan Ermilov data = malloc(sizeof(_RuneLocale) + 15377bc2a1cSRuslan Bukin (BSWAP(frl->runetype_ext_nranges) + BSWAP(frl->maplower_ext_nranges) + 15477bc2a1cSRuslan Bukin BSWAP(frl->mapupper_ext_nranges)) * sizeof(_RuneEntry) + 1553fb3a430SRuslan Ermilov runetype_ext_len * sizeof(*rr->__types) + 15677bc2a1cSRuslan Bukin BSWAP(frl->variable_len)); 1573fb3a430SRuslan Ermilov if (data == NULL) { 1583fb3a430SRuslan Ermilov saverr = errno; 1597b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 1603fb3a430SRuslan Ermilov errno = saverr; 1613fb3a430SRuslan Ermilov return (NULL); 1623fb3a430SRuslan Ermilov } 1633fb3a430SRuslan Ermilov 1643fb3a430SRuslan Ermilov rl = (_RuneLocale *)data; 1653fb3a430SRuslan Ermilov rl->__variable = rl + 1; 1663fb3a430SRuslan Ermilov 1673fb3a430SRuslan Ermilov memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic)); 1683fb3a430SRuslan Ermilov memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding)); 1693fb3a430SRuslan Ermilov 17077bc2a1cSRuslan Bukin rl->__variable_len = BSWAP(frl->variable_len); 17177bc2a1cSRuslan Bukin rl->__runetype_ext.__nranges = BSWAP(frl->runetype_ext_nranges); 17277bc2a1cSRuslan Bukin rl->__maplower_ext.__nranges = BSWAP(frl->maplower_ext_nranges); 17377bc2a1cSRuslan Bukin rl->__mapupper_ext.__nranges = BSWAP(frl->mapupper_ext_nranges); 1743fb3a430SRuslan Ermilov 1753fb3a430SRuslan Ermilov for (x = 0; x < _CACHED_RUNES; ++x) { 17677bc2a1cSRuslan Bukin rl->__runetype[x] = BSWAP(frl->runetype[x]); 17777bc2a1cSRuslan Bukin rl->__maplower[x] = BSWAP(frl->maplower[x]); 17877bc2a1cSRuslan Bukin rl->__mapupper[x] = BSWAP(frl->mapupper[x]); 1793fb3a430SRuslan Ermilov } 1803fb3a430SRuslan Ermilov 1813fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable; 1823fb3a430SRuslan Ermilov rl->__variable = rl->__runetype_ext.__ranges + 1833fb3a430SRuslan Ermilov rl->__runetype_ext.__nranges; 1843fb3a430SRuslan Ermilov 1853fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable; 1863fb3a430SRuslan Ermilov rl->__variable = rl->__maplower_ext.__ranges + 1873fb3a430SRuslan Ermilov rl->__maplower_ext.__nranges; 1883fb3a430SRuslan Ermilov 1893fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable; 1903fb3a430SRuslan Ermilov rl->__variable = rl->__mapupper_ext.__ranges + 1913fb3a430SRuslan Ermilov rl->__mapupper_ext.__nranges; 1923fb3a430SRuslan Ermilov 19377bc2a1cSRuslan Bukin variable = mapupper_ext_ranges + BSWAP(frl->mapupper_ext_nranges); 1943fb3a430SRuslan Ermilov frr = runetype_ext_ranges; 1953fb3a430SRuslan Ermilov rr = rl->__runetype_ext.__ranges; 1963fb3a430SRuslan Ermilov for (x = 0; x < rl->__runetype_ext.__nranges; ++x) { 1973fb3a430SRuslan Ermilov uint32_t *types; 1983fb3a430SRuslan Ermilov 19977bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 20077bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 20177bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2023fb3a430SRuslan Ermilov if (rr[x].__map == 0) { 2033fb3a430SRuslan Ermilov int len = rr[x].__max - rr[x].__min + 1; 2043fb3a430SRuslan Ermilov types = variable; 2053fb3a430SRuslan Ermilov variable = types + len; 2063fb3a430SRuslan Ermilov rr[x].__types = rl->__variable; 2073fb3a430SRuslan Ermilov rl->__variable = rr[x].__types + len; 2083fb3a430SRuslan Ermilov while (len-- > 0) 2093fb3a430SRuslan Ermilov rr[x].__types[len] = types[len]; 2103fb3a430SRuslan Ermilov } else 2113fb3a430SRuslan Ermilov rr[x].__types = NULL; 2123fb3a430SRuslan Ermilov } 2133fb3a430SRuslan Ermilov 2143fb3a430SRuslan Ermilov frr = maplower_ext_ranges; 2153fb3a430SRuslan Ermilov rr = rl->__maplower_ext.__ranges; 2163fb3a430SRuslan Ermilov for (x = 0; x < rl->__maplower_ext.__nranges; ++x) { 21777bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 21877bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 21977bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2203fb3a430SRuslan Ermilov } 2213fb3a430SRuslan Ermilov 2223fb3a430SRuslan Ermilov frr = mapupper_ext_ranges; 2233fb3a430SRuslan Ermilov rr = rl->__mapupper_ext.__ranges; 2243fb3a430SRuslan Ermilov for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) { 22577bc2a1cSRuslan Bukin rr[x].__min = BSWAP(frr[x].min); 22677bc2a1cSRuslan Bukin rr[x].__max = BSWAP(frr[x].max); 22777bc2a1cSRuslan Bukin rr[x].__map = BSWAP(frr[x].map); 2283fb3a430SRuslan Ermilov } 2293fb3a430SRuslan Ermilov 2303fb3a430SRuslan Ermilov memcpy(rl->__variable, variable, rl->__variable_len); 2317b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 2323fb3a430SRuslan Ermilov 2333fb3a430SRuslan Ermilov /* 234350a3d3eSAndrey A. Chernov * Go out and zero pointers that should be zero. 235350a3d3eSAndrey A. Chernov */ 236ddc1ededSTim J. Robbins if (!rl->__variable_len) 2373fb3a430SRuslan Ermilov rl->__variable = NULL; 238350a3d3eSAndrey A. Chernov 239ddc1ededSTim J. Robbins if (!rl->__runetype_ext.__nranges) 2403fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = NULL; 241350a3d3eSAndrey A. Chernov 242ddc1ededSTim J. Robbins if (!rl->__maplower_ext.__nranges) 2433fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = NULL; 244350a3d3eSAndrey A. Chernov 245ddc1ededSTim J. Robbins if (!rl->__mapupper_ext.__nranges) 2463fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = NULL; 247350a3d3eSAndrey A. Chernov 248350a3d3eSAndrey A. Chernov return (rl); 2497b247341SBaptiste Daroussin 2507b247341SBaptiste Daroussin invalid: 2517b247341SBaptiste Daroussin munmap(fdata, sb.st_size); 2527b247341SBaptiste Daroussin errno = EINVAL; 2537b247341SBaptiste Daroussin return (NULL); 254350a3d3eSAndrey A. Chernov } 255