1/*-
2 * Copyright (c) 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Paul Borman at Krystal Technologies.
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 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef RUNEOFF32
38#if defined(LIBC_SCCS) && !defined(lint)
39static char sccsid[] = "@(#)rune.c	8.1 (Berkeley) 6/4/93";
40#endif /* LIBC_SCCS and not lint */
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: src/lib/libc/locale/rune.c,v 1.12 2004/07/29 06:16:19 tjr Exp $");
43
44#include "xlocale_private.h"
45
46#include "namespace.h"
47#include <arpa/inet.h>
48#include <errno.h>
49#include <runetype.h>
50#else
51#include "runetype.h"
52#endif /* !RUNEOFF32 */
53#include <stdio.h>
54#ifndef RUNEOFF32
55#include <string.h>
56#include <stdlib.h>
57#include <sys/types.h>
58#include <sys/stat.h>
59#include "un-namespace.h"
60#endif /* !RUNEOFF32 */
61
62#if defined(__LP64__) || defined(RUNEOFF32)
63/*
64 * Because the LC_CTYPE files were created with a 32-bit program, we need
65 * to adjust for the larger pointers in LP64 (the longs have already been
66 * replaced by 32-bit equivalents).  Also, natural alignment will pad
67 * 64-bit types to 8-byte boundaries, and make structures containing
68 * 64-bit types sized to 8-byte boundaries.
69 */
70#include <stddef.h>
71#ifndef RUNEOFF32
72#include "rune32.h"
73#define BYTES32BITS		4
74#define BYTES64BITS		8
75/* whether to skip over a pointer or not (one-to-one with off64) */
76int skip[] = {
77	1,
78	1,
79	0,
80	1,
81	0,
82	1,
83	0,
84	1,
85	1,
86	1,
87	0
88};
89#endif /* !RUNEOFF32 */
90int off64[] = {
91	offsetof(_RuneLocale, __sgetrune),
92	offsetof(_RuneLocale, __sputrune),
93	offsetof(_RuneLocale, __runetype_ext),
94	offsetof(_RuneLocale, __runetype_ext) + offsetof(_RuneRange, __ranges),
95	offsetof(_RuneLocale, __maplower_ext),
96	offsetof(_RuneLocale, __maplower_ext) + offsetof(_RuneRange, __ranges),
97	offsetof(_RuneLocale, __mapupper_ext),
98	offsetof(_RuneLocale, __mapupper_ext) + offsetof(_RuneRange, __ranges),
99	offsetof(_RuneLocale, __variable),
100	offsetof(_RuneLocale, __charclasses),
101	sizeof(_RuneLocale)
102};
103#define	NOFF			(sizeof(off64) / sizeof(int))
104#ifdef RUNEOFF32
105/*
106 * This program generates a header file (on stdout) that containes the 32-bit
107 * offsets, plus some 32-bit sizes
108 */
109main()
110{
111	int i;
112	printf("#define SIZEOF32_RUNEENTRY %d\n", sizeof(_RuneEntry));
113	printf("#define SIZEOF32_RUNELOCALE %d\n", sizeof(_RuneLocale));
114	printf("int off32[] = {\n");
115	for(i = 0; i < NOFF; i++)
116		printf("\t%d,\n", off64[i]);
117	printf("};\n");
118	return 0;
119}
120#endif /* RUNEOFF32 */
121#else /* !__LP64__ && !RUNEOFF32 */
122#define	SIZEOF32_RUNELOCALE	sizeof(_RuneLocale)
123#endif /* __LP64__ || RUNEOFF32 */
124
125#ifndef RUNEOFF32
126struct __xlocale_st_runelocale *
127_Read_RuneMagi(fp)
128	FILE *fp;
129{
130	struct __xlocale_st_runelocale *data;
131	void *lastp;
132	_RuneLocale *rl;
133	_RuneEntry *rr;
134	struct stat sb;
135	int x, saverr;
136
137	if (_fstat(fileno(fp), &sb) < 0)
138		return (NULL);
139
140	if (sb.st_size < SIZEOF32_RUNELOCALE) {
141		errno = EFTYPE;
142		return (NULL);
143	}
144
145#ifdef __LP64__
146	/* will adjust later */
147	if ((data = (struct __xlocale_st_runelocale *)malloc(sizeof(struct __xlocale_st_runelocale))) == NULL)
148#else /* !__LP64__ */
149	if ((data = (struct __xlocale_st_runelocale *)malloc(sizeof(struct __xlocale_st_runelocale) - sizeof(_RuneLocale) + sb.st_size)) == NULL)
150#endif /* __LP64__ */
151		return (NULL);
152	data->__refcount = 1;
153	data->__free_extra = NULL;
154
155	errno = 0;
156	rewind(fp); /* Someone might have read the magic number once already */
157	if (errno) {
158		saverr = errno;
159		free(data);
160		errno = saverr;
161		return (NULL);
162	}
163
164	rl = &data->_CurrentRuneLocale;
165
166#ifdef __LP64__
167	if (fread(rl, SIZEOF32_RUNELOCALE, 1, fp) != 1)
168#else /* !__LP64__ */
169	if (fread(rl, sb.st_size, 1, fp) != 1)
170#endif /* __LP64__ */
171	{
172		saverr = errno;
173		free(data);
174		errno = saverr;
175		return (NULL);
176	}
177
178#ifndef __LP64__
179	lastp = (char *)rl + sb.st_size;
180
181	rl->__variable = rl + 1;
182#endif /* __LP64__ */
183
184	if (memcmp(rl->__magic, _RUNE_MAGIC_A, sizeof(rl->__magic))) {
185		free(data);
186		errno = EFTYPE;
187		return (NULL);
188	}
189
190#ifdef __LP64__
191	/* shift things into the right position */
192	for (x = NOFF - 2; x >= 0; x--)
193		memmove((char *)rl + off64[x] + (skip[x] ? BYTES64BITS : 0),
194			(char *)rl + off32[x] + (skip[x] ? BYTES32BITS : 0),
195			off32[x + 1] - off32[x] - (skip[x] ? BYTES32BITS : 0));
196#endif /* __LP64__ */
197#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
198	rl->__invalid_rune = ntohl(rl->__invalid_rune);
199	rl->__variable_len = ntohl(rl->__variable_len);
200	rl->__ncharclasses = ntohl(rl->__ncharclasses);
201	rl->__runetype_ext.__nranges = ntohl(rl->__runetype_ext.__nranges);
202	rl->__maplower_ext.__nranges = ntohl(rl->__maplower_ext.__nranges);
203	rl->__mapupper_ext.__nranges = ntohl(rl->__mapupper_ext.__nranges);
204
205	for (x = 0; x < _CACHED_RUNES; ++x) {
206		rl->__runetype[x] = ntohl(rl->__runetype[x]);
207		rl->__maplower[x] = ntohl(rl->__maplower[x]);
208		rl->__mapupper[x] = ntohl(rl->__mapupper[x]);
209	}
210#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
211
212#ifdef __LP64__
213	{
214	int count = rl->__runetype_ext.__nranges + rl->__maplower_ext.__nranges
215	    + rl->__mapupper_ext.__nranges;
216	int extra = sb.st_size - SIZEOF32_RUNELOCALE - count * SIZEOF32_RUNEENTRY - rl->__ncharclasses * sizeof(_RuneCharClass);
217	_RuneEntry *rp;
218
219	if (extra < 0) {
220		saverr = errno;
221		free(data);
222		errno = saverr;
223		return (NULL);
224	}
225	if ((data = (struct __xlocale_st_runelocale *)reallocf(data, sizeof(struct __xlocale_st_runelocale)
226	    + count * sizeof(_RuneEntry)
227	    + rl->__ncharclasses * sizeof(_RuneCharClass)
228	    + extra)) == NULL)
229		return (NULL);
230	rl = &data->_CurrentRuneLocale;
231	rl->__variable = rl + 1;
232	rp = (_RuneEntry *)rl->__variable;
233	for (x = 0; x < count; x++, rp++)
234		if (fread(rp, SIZEOF32_RUNEENTRY, 1, fp) != 1) {
235			saverr = errno;
236			free(data);
237			errno = saverr;
238			return (NULL);
239		}
240	if (rl->__ncharclasses > 0) {
241		if (fread(rp, sizeof(_RuneCharClass), rl->__ncharclasses, fp) != rl->__ncharclasses) {
242			saverr = errno;
243			free(data);
244			errno = saverr;
245			return (NULL);
246		}
247		rp = (_RuneEntry *)((char *)rp + rl->__ncharclasses * sizeof(_RuneCharClass));
248	}
249	if (extra > 0 && fread(rp, extra, 1, fp) != 1) {
250		saverr = errno;
251		free(data);
252		errno = saverr;
253		return (NULL);
254	}
255	lastp = (char *)rp + extra;
256	}
257#endif /* __LP64__ */
258	rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
259	rl->__variable = rl->__runetype_ext.__ranges +
260	    rl->__runetype_ext.__nranges;
261	if (rl->__variable > lastp) {
262		free(data);
263		errno = EFTYPE;
264		return (NULL);
265	}
266
267	rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable;
268	rl->__variable = rl->__maplower_ext.__ranges +
269	    rl->__maplower_ext.__nranges;
270	if (rl->__variable > lastp) {
271		free(data);
272		errno = EFTYPE;
273		return (NULL);
274	}
275
276	rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable;
277	rl->__variable = rl->__mapupper_ext.__ranges +
278	    rl->__mapupper_ext.__nranges;
279	if (rl->__variable > lastp) {
280		free(data);
281		errno = EFTYPE;
282		return (NULL);
283	}
284
285	for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
286		rr = rl->__runetype_ext.__ranges;
287
288#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
289		rr[x].__min = ntohl(rr[x].__min);
290		rr[x].__max = ntohl(rr[x].__max);
291#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
292		if ((rr[x].__map = ntohl(rr[x].__map)) == 0) {
293			int len = rr[x].__max - rr[x].__min + 1;
294			rr[x].__types = rl->__variable;
295			rl->__variable = rr[x].__types + len;
296			if (rl->__variable > lastp) {
297				free(data);
298				errno = EFTYPE;
299				return (NULL);
300			}
301#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
302			while (len-- > 0)
303				rr[x].__types[len] = ntohl(rr[x].__types[len]);
304#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
305		} else
306			rr[x].__types = 0;
307	}
308
309#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
310	for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
311		rr = rl->__maplower_ext.__ranges;
312
313		rr[x].__min = ntohl(rr[x].__min);
314		rr[x].__max = ntohl(rr[x].__max);
315		rr[x].__map = ntohl(rr[x].__map);
316	}
317
318	for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) {
319		rr = rl->__mapupper_ext.__ranges;
320
321		rr[x].__min = ntohl(rr[x].__min);
322		rr[x].__max = ntohl(rr[x].__max);
323		rr[x].__map = ntohl(rr[x].__map);
324	}
325#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
326
327	if (rl->__ncharclasses > 0) {
328		rl->__charclasses = (_RuneCharClass *)rl->__variable;
329		rl->__variable = (void *)(rl->__charclasses + rl->__ncharclasses);
330		if (rl->__variable > lastp) {
331			free(data);
332			errno = EFTYPE;
333			return (NULL);
334		}
335#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
336		for (x = 0; x < rl->__ncharclasses; ++x)
337			rl->__charclasses[x].__mask = ntohl(rl->__charclasses[x].__mask);
338#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
339	}
340
341	if (((char *)rl->__variable) + rl->__variable_len > (char *)lastp) {
342		free(data);
343		errno = EFTYPE;
344		return (NULL);
345	}
346
347	/*
348	 * Go out and zero pointers that should be zero.
349	 */
350	if (!rl->__variable_len)
351		rl->__variable = 0;
352
353	if (!rl->__runetype_ext.__nranges)
354		rl->__runetype_ext.__ranges = 0;
355
356	if (!rl->__maplower_ext.__nranges)
357		rl->__maplower_ext.__ranges = 0;
358
359	if (!rl->__mapupper_ext.__nranges)
360		rl->__mapupper_ext.__ranges = 0;
361
362	data->__datasize = lastp - (void *)data;
363	return (data);
364}
365#endif /* !RUNEOFF32 */
366