Merge from vendor branch NTPD:
[dragonfly.git] / lib / libc / locale / rune.c
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  * @(#)rune.c   8.1 (Berkeley) 6/4/93
37  * $FreeBSD: src/lib/libc/locale/rune.c,v 1.5.8.2 2002/08/12 11:17:38 ache Exp $
38  * $DragonFly: src/lib/libc/locale/rune.c,v 1.3 2005/01/31 22:29:31 dillon Exp $
39  */
40
41 #include "namespace.h"
42 #include <arpa/inet.h>
43 #include <errno.h>
44 #include <rune.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include "un-namespace.h"
51
52 _RuneLocale *
53 _Read_RuneMagi(fp)
54         FILE *fp;
55 {
56         char *data;
57         void *lastp;
58         _RuneLocale *rl;
59         _RuneEntry *rr;
60         struct stat sb;
61         int x, saverr;
62
63         if (_fstat(fileno(fp), &sb) < 0)
64                 return (NULL);
65
66         if (sb.st_size < sizeof(_RuneLocale)) {
67                 errno = EFTYPE;
68                 return (NULL);
69         }
70
71         if ((data = malloc(sb.st_size)) == NULL)
72                 return (NULL);
73
74         errno = 0;
75         rewind(fp); /* Someone might have read the magic number once already */
76         if (errno) {
77                 saverr = errno;
78                 free(data);
79                 errno = saverr;
80                 return (NULL);
81         }
82
83         if (fread(data, sb.st_size, 1, fp) != 1) {
84                 saverr = errno;
85                 free(data);
86                 errno = saverr;
87                 return (NULL);
88         }
89
90         rl = (_RuneLocale *)data;
91         lastp = data + sb.st_size;
92
93         rl->variable = rl + 1;
94
95         if (memcmp(rl->magic, _RUNE_MAGIC_1, sizeof(rl->magic))) {
96                 free(data);
97                 errno = EFTYPE;
98                 return (NULL);
99         }
100
101         rl->invalid_rune = ntohl(rl->invalid_rune);
102         rl->variable_len = ntohl(rl->variable_len);
103         rl->runetype_ext.nranges = ntohl(rl->runetype_ext.nranges);
104         rl->maplower_ext.nranges = ntohl(rl->maplower_ext.nranges);
105         rl->mapupper_ext.nranges = ntohl(rl->mapupper_ext.nranges);
106
107         for (x = 0; x < _CACHED_RUNES; ++x) {
108                 rl->runetype[x] = ntohl(rl->runetype[x]);
109                 rl->maplower[x] = ntohl(rl->maplower[x]);
110                 rl->mapupper[x] = ntohl(rl->mapupper[x]);
111         }
112
113         rl->runetype_ext.ranges = (_RuneEntry *)rl->variable;
114         rl->variable = rl->runetype_ext.ranges + rl->runetype_ext.nranges;
115         if (rl->variable > lastp) {
116                 free(data);
117                 errno = EFTYPE;
118                 return (NULL);
119         }
120
121         rl->maplower_ext.ranges = (_RuneEntry *)rl->variable;
122         rl->variable = rl->maplower_ext.ranges + rl->maplower_ext.nranges;
123         if (rl->variable > lastp) {
124                 free(data);
125                 errno = EFTYPE;
126                 return (NULL);
127         }
128
129         rl->mapupper_ext.ranges = (_RuneEntry *)rl->variable;
130         rl->variable = rl->mapupper_ext.ranges + rl->mapupper_ext.nranges;
131         if (rl->variable > lastp) {
132                 free(data);
133                 errno = EFTYPE;
134                 return (NULL);
135         }
136
137         for (x = 0; x < rl->runetype_ext.nranges; ++x) {
138                 rr = rl->runetype_ext.ranges;
139
140                 rr[x].min = ntohl(rr[x].min);
141                 rr[x].max = ntohl(rr[x].max);
142                 if ((rr[x].map = ntohl(rr[x].map)) == 0) {
143                         int len = rr[x].max - rr[x].min + 1;
144                         rr[x].types = rl->variable;
145                         rl->variable = rr[x].types + len;
146                         if (rl->variable > lastp) {
147                                 free(data);
148                                 errno = EFTYPE;
149                                 return (NULL);
150                         }
151                         while (len-- > 0)
152                                 rr[x].types[len] = ntohl(rr[x].types[len]);
153                 } else
154                         rr[x].types = 0;
155         }
156
157         for (x = 0; x < rl->maplower_ext.nranges; ++x) {
158                 rr = rl->maplower_ext.ranges;
159
160                 rr[x].min = ntohl(rr[x].min);
161                 rr[x].max = ntohl(rr[x].max);
162                 rr[x].map = ntohl(rr[x].map);
163         }
164
165         for (x = 0; x < rl->mapupper_ext.nranges; ++x) {
166                 rr = rl->mapupper_ext.ranges;
167
168                 rr[x].min = ntohl(rr[x].min);
169                 rr[x].max = ntohl(rr[x].max);
170                 rr[x].map = ntohl(rr[x].map);
171         }
172         if (((char *)rl->variable) + rl->variable_len > (char *)lastp) {
173                 free(data);
174                 errno = EFTYPE;
175                 return (NULL);
176         }
177
178         /*
179          * Go out and zero pointers that should be zero.
180          */
181         if (!rl->variable_len)
182                 rl->variable = 0;
183
184         if (!rl->runetype_ext.nranges)
185                 rl->runetype_ext.ranges = 0;
186
187         if (!rl->maplower_ext.nranges)
188                 rl->maplower_ext.ranges = 0;
189
190         if (!rl->mapupper_ext.nranges)
191                 rl->mapupper_ext.ranges = 0;
192
193         return (rl);
194 }