158f0484fSRodney W. Grimes /*-
28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro 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
37d201fe46SDaniel Eischen #include "namespace.h"
38fd8e4ebcSMike Barcroft #include <arpa/inet.h>
3976692b80SAndrey A. Chernov #include <errno.h>
40a0998ce6STim J. Robbins #include <runetype.h>
4158f0484fSRodney W. Grimes #include <stdio.h>
42350a3d3eSAndrey A. Chernov #include <string.h>
4358f0484fSRodney W. Grimes #include <stdlib.h>
44350a3d3eSAndrey A. Chernov #include <sys/types.h>
45350a3d3eSAndrey A. Chernov #include <sys/stat.h>
467b247341SBaptiste Daroussin #include <sys/mman.h>
477b247341SBaptiste Daroussin #include <fcntl.h>
487b247341SBaptiste Daroussin #include <unistd.h>
49d201fe46SDaniel Eischen #include "un-namespace.h"
5058f0484fSRodney W. Grimes
51228f8c4fSRuslan Ermilov #include "runefile.h"
52228f8c4fSRuslan Ermilov
53350a3d3eSAndrey A. Chernov _RuneLocale *
_Read_RuneMagi(const char * fname)547b247341SBaptiste Daroussin _Read_RuneMagi(const char *fname)
55350a3d3eSAndrey A. Chernov {
563fb3a430SRuslan Ermilov char *fdata, *data;
57350a3d3eSAndrey A. Chernov void *lastp;
583fb3a430SRuslan Ermilov _FileRuneLocale *frl;
59350a3d3eSAndrey A. Chernov _RuneLocale *rl;
603fb3a430SRuslan Ermilov _FileRuneEntry *frr;
61350a3d3eSAndrey A. Chernov _RuneEntry *rr;
62350a3d3eSAndrey A. Chernov struct stat sb;
6376692b80SAndrey A. Chernov int x, saverr;
643fb3a430SRuslan Ermilov void *variable;
653fb3a430SRuslan Ermilov _FileRuneEntry *runetype_ext_ranges;
663fb3a430SRuslan Ermilov _FileRuneEntry *maplower_ext_ranges;
673fb3a430SRuslan Ermilov _FileRuneEntry *mapupper_ext_ranges;
683fb3a430SRuslan Ermilov int runetype_ext_len = 0;
697b247341SBaptiste Daroussin int fd;
70350a3d3eSAndrey A. Chernov
71*98bfb9daSMark Johnston if ((fd = _open(fname, O_RDONLY | O_CLOEXEC)) < 0) {
727b247341SBaptiste Daroussin errno = EINVAL;
7376692b80SAndrey A. Chernov return (NULL);
747b247341SBaptiste Daroussin }
757b247341SBaptiste Daroussin
767b247341SBaptiste Daroussin if (_fstat(fd, &sb) < 0) {
777b247341SBaptiste Daroussin (void) _close(fd);
787b247341SBaptiste Daroussin errno = EINVAL;
797b247341SBaptiste Daroussin return (NULL);
807b247341SBaptiste Daroussin }
81350a3d3eSAndrey A. Chernov
823fb3a430SRuslan Ermilov if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) {
837b247341SBaptiste Daroussin (void) _close(fd);
847b247341SBaptiste Daroussin errno = EINVAL;
8576692b80SAndrey A. Chernov return (NULL);
8676692b80SAndrey A. Chernov }
87350a3d3eSAndrey A. Chernov
88350a3d3eSAndrey A. Chernov
897b247341SBaptiste Daroussin fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
907b247341SBaptiste Daroussin (void) _close(fd);
9157e64236SMark Johnston if (fdata == MAP_FAILED) {
927b247341SBaptiste Daroussin errno = EINVAL;
9376692b80SAndrey A. Chernov return (NULL);
9476692b80SAndrey A. Chernov }
95350a3d3eSAndrey A. Chernov
967b247341SBaptiste Daroussin frl = (_FileRuneLocale *)(void *)fdata;
973fb3a430SRuslan Ermilov lastp = fdata + sb.st_size;
98350a3d3eSAndrey A. Chernov
993fb3a430SRuslan Ermilov variable = frl + 1;
100350a3d3eSAndrey A. Chernov
1013fb3a430SRuslan Ermilov if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) {
1027b247341SBaptiste Daroussin goto invalid;
103350a3d3eSAndrey A. Chernov }
104350a3d3eSAndrey A. Chernov
1053fb3a430SRuslan Ermilov runetype_ext_ranges = (_FileRuneEntry *)variable;
1064644f9beSYuri Pankov variable = runetype_ext_ranges + frl->runetype_ext_nranges;
1073fb3a430SRuslan Ermilov if (variable > lastp) {
1087b247341SBaptiste Daroussin goto invalid;
109350a3d3eSAndrey A. Chernov }
110350a3d3eSAndrey A. Chernov
1113fb3a430SRuslan Ermilov maplower_ext_ranges = (_FileRuneEntry *)variable;
1124644f9beSYuri Pankov variable = maplower_ext_ranges + frl->maplower_ext_nranges;
1133fb3a430SRuslan Ermilov if (variable > lastp) {
1147b247341SBaptiste Daroussin goto invalid;
115350a3d3eSAndrey A. Chernov }
116350a3d3eSAndrey A. Chernov
1173fb3a430SRuslan Ermilov mapupper_ext_ranges = (_FileRuneEntry *)variable;
1184644f9beSYuri Pankov variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
1193fb3a430SRuslan Ermilov if (variable > lastp) {
1207b247341SBaptiste Daroussin goto invalid;
121350a3d3eSAndrey A. Chernov }
122350a3d3eSAndrey A. Chernov
1233fb3a430SRuslan Ermilov frr = runetype_ext_ranges;
1244644f9beSYuri Pankov for (x = 0; x < frl->runetype_ext_nranges; ++x) {
1253fb3a430SRuslan Ermilov uint32_t *types;
126350a3d3eSAndrey A. Chernov
1274644f9beSYuri Pankov if (frr[x].map == 0) {
1284644f9beSYuri Pankov int len = frr[x].max - frr[x].min + 1;
1293fb3a430SRuslan Ermilov types = variable;
1303fb3a430SRuslan Ermilov variable = types + len;
1313fb3a430SRuslan Ermilov runetype_ext_len += len;
1323fb3a430SRuslan Ermilov if (variable > lastp) {
1337b247341SBaptiste Daroussin goto invalid;
134350a3d3eSAndrey A. Chernov }
1353fb3a430SRuslan Ermilov }
136350a3d3eSAndrey A. Chernov }
137350a3d3eSAndrey A. Chernov
1384644f9beSYuri Pankov if ((char *)variable + frl->variable_len > (char *)lastp) {
1397b247341SBaptiste Daroussin goto invalid;
140350a3d3eSAndrey A. Chernov }
141350a3d3eSAndrey A. Chernov
142350a3d3eSAndrey A. Chernov /*
1433fb3a430SRuslan Ermilov * Convert from disk format to host format.
1443fb3a430SRuslan Ermilov */
1453fb3a430SRuslan Ermilov data = malloc(sizeof(_RuneLocale) +
1464644f9beSYuri Pankov (frl->runetype_ext_nranges + frl->maplower_ext_nranges +
1474644f9beSYuri Pankov frl->mapupper_ext_nranges) * sizeof(_RuneEntry) +
1484644f9beSYuri Pankov runetype_ext_len * sizeof(*rr->__types) + frl->variable_len);
1493fb3a430SRuslan Ermilov if (data == NULL) {
1503fb3a430SRuslan Ermilov saverr = errno;
1517b247341SBaptiste Daroussin munmap(fdata, sb.st_size);
1523fb3a430SRuslan Ermilov errno = saverr;
1533fb3a430SRuslan Ermilov return (NULL);
1543fb3a430SRuslan Ermilov }
1553fb3a430SRuslan Ermilov
1563fb3a430SRuslan Ermilov rl = (_RuneLocale *)data;
1573fb3a430SRuslan Ermilov rl->__variable = rl + 1;
1583fb3a430SRuslan Ermilov
1593fb3a430SRuslan Ermilov memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic));
1603fb3a430SRuslan Ermilov memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding));
1613fb3a430SRuslan Ermilov
1624644f9beSYuri Pankov rl->__variable_len = frl->variable_len;
1634644f9beSYuri Pankov rl->__runetype_ext.__nranges = frl->runetype_ext_nranges;
1644644f9beSYuri Pankov rl->__maplower_ext.__nranges = frl->maplower_ext_nranges;
1654644f9beSYuri Pankov rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges;
1663fb3a430SRuslan Ermilov
1673fb3a430SRuslan Ermilov for (x = 0; x < _CACHED_RUNES; ++x) {
1684644f9beSYuri Pankov rl->__runetype[x] = frl->runetype[x];
1694644f9beSYuri Pankov rl->__maplower[x] = frl->maplower[x];
1704644f9beSYuri Pankov rl->__mapupper[x] = frl->mapupper[x];
1713fb3a430SRuslan Ermilov }
1723fb3a430SRuslan Ermilov
1733fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
1743fb3a430SRuslan Ermilov rl->__variable = rl->__runetype_ext.__ranges +
1753fb3a430SRuslan Ermilov rl->__runetype_ext.__nranges;
1763fb3a430SRuslan Ermilov
1773fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable;
1783fb3a430SRuslan Ermilov rl->__variable = rl->__maplower_ext.__ranges +
1793fb3a430SRuslan Ermilov rl->__maplower_ext.__nranges;
1803fb3a430SRuslan Ermilov
1813fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable;
1823fb3a430SRuslan Ermilov rl->__variable = rl->__mapupper_ext.__ranges +
1833fb3a430SRuslan Ermilov rl->__mapupper_ext.__nranges;
1843fb3a430SRuslan Ermilov
1854644f9beSYuri Pankov variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
1863fb3a430SRuslan Ermilov frr = runetype_ext_ranges;
1873fb3a430SRuslan Ermilov rr = rl->__runetype_ext.__ranges;
1883fb3a430SRuslan Ermilov for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
1893fb3a430SRuslan Ermilov uint32_t *types;
1903fb3a430SRuslan Ermilov
1914644f9beSYuri Pankov rr[x].__min = frr[x].min;
1924644f9beSYuri Pankov rr[x].__max = frr[x].max;
1934644f9beSYuri Pankov rr[x].__map = frr[x].map;
1943fb3a430SRuslan Ermilov if (rr[x].__map == 0) {
1953fb3a430SRuslan Ermilov int len = rr[x].__max - rr[x].__min + 1;
1963fb3a430SRuslan Ermilov types = variable;
1973fb3a430SRuslan Ermilov variable = types + len;
1983fb3a430SRuslan Ermilov rr[x].__types = rl->__variable;
1993fb3a430SRuslan Ermilov rl->__variable = rr[x].__types + len;
2003fb3a430SRuslan Ermilov while (len-- > 0)
2013fb3a430SRuslan Ermilov rr[x].__types[len] = types[len];
2023fb3a430SRuslan Ermilov } else
2033fb3a430SRuslan Ermilov rr[x].__types = NULL;
2043fb3a430SRuslan Ermilov }
2053fb3a430SRuslan Ermilov
2063fb3a430SRuslan Ermilov frr = maplower_ext_ranges;
2073fb3a430SRuslan Ermilov rr = rl->__maplower_ext.__ranges;
2083fb3a430SRuslan Ermilov for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
2094644f9beSYuri Pankov rr[x].__min = frr[x].min;
2104644f9beSYuri Pankov rr[x].__max = frr[x].max;
2114644f9beSYuri Pankov rr[x].__map = frr[x].map;
2123fb3a430SRuslan Ermilov }
2133fb3a430SRuslan Ermilov
2143fb3a430SRuslan Ermilov frr = mapupper_ext_ranges;
2153fb3a430SRuslan Ermilov rr = rl->__mapupper_ext.__ranges;
2163fb3a430SRuslan Ermilov for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) {
2174644f9beSYuri Pankov rr[x].__min = frr[x].min;
2184644f9beSYuri Pankov rr[x].__max = frr[x].max;
2194644f9beSYuri Pankov rr[x].__map = frr[x].map;
2203fb3a430SRuslan Ermilov }
2213fb3a430SRuslan Ermilov
2223fb3a430SRuslan Ermilov memcpy(rl->__variable, variable, rl->__variable_len);
2237b247341SBaptiste Daroussin munmap(fdata, sb.st_size);
2243fb3a430SRuslan Ermilov
2253fb3a430SRuslan Ermilov /*
226350a3d3eSAndrey A. Chernov * Go out and zero pointers that should be zero.
227350a3d3eSAndrey A. Chernov */
228ddc1ededSTim J. Robbins if (!rl->__variable_len)
2293fb3a430SRuslan Ermilov rl->__variable = NULL;
230350a3d3eSAndrey A. Chernov
231ddc1ededSTim J. Robbins if (!rl->__runetype_ext.__nranges)
2323fb3a430SRuslan Ermilov rl->__runetype_ext.__ranges = NULL;
233350a3d3eSAndrey A. Chernov
234ddc1ededSTim J. Robbins if (!rl->__maplower_ext.__nranges)
2353fb3a430SRuslan Ermilov rl->__maplower_ext.__ranges = NULL;
236350a3d3eSAndrey A. Chernov
237ddc1ededSTim J. Robbins if (!rl->__mapupper_ext.__nranges)
2383fb3a430SRuslan Ermilov rl->__mapupper_ext.__ranges = NULL;
239350a3d3eSAndrey A. Chernov
240350a3d3eSAndrey A. Chernov return (rl);
2417b247341SBaptiste Daroussin
2427b247341SBaptiste Daroussin invalid:
2437b247341SBaptiste Daroussin munmap(fdata, sb.st_size);
2447b247341SBaptiste Daroussin errno = EINVAL;
2457b247341SBaptiste Daroussin return (NULL);
246350a3d3eSAndrey A. Chernov }
247