xref: /freebsd/lib/libc/locale/rune.c (revision dc36d6f9)
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 
7198bfb9daSMark 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