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