Print this page
smatch clean rtld
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/rtld/common/locale.c
+++ new/usr/src/cmd/sgs/rtld/common/locale.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * Messaging support. To minimize ld.so.1's overhead, messaging support isn't
29 29 * enabled until we need to contruct a message - Note that we don't rely on the
30 30 * application to signify whether messaging is applicable, as many message
31 31 * conditions (such as relocations) are generated before the application gains
32 32 * control.
33 33 *
34 34 * This code implements a very trimmed down version of the capabilities found
35 35 * via setlocale(3c), textdomain(3i) and gettext(3i). Dragging in the original
36 36 * routines from libc/libintl isn't possible as they cause all i18n support to
37 37 * be included which is far too expensive for ld.so.1.
38 38 */
39 39
40 40 #include <sys/types.h>
41 41 #include <sys/mman.h>
42 42 #include <sys/stat.h>
43 43 #include <string.h>
44 44 #include <stdio.h>
45 45 #include <stdlib.h>
46 46 #include <unistd.h>
47 47 #include <fcntl.h>
48 48 #include <limits.h>
49 49 #include <libintl.h>
50 50 #include "_rtld.h"
51 51 #include "msg.h"
52 52
53 53 /*
54 54 * A message object file (as generated by msgfmt(1)) consists of a message
55 55 * header, followed by a message list, followed by the msgid strings and then
56 56 * the msgstr strings. None of this is defined in any OSNET available headers
57 57 * so we have our own local definitions :-(
58 58 */
59 59 typedef struct {
60 60 int hdr_midlst; /* middle message no. */
61 61 int hdr_lstcnt; /* total no. of message in the file */
62 62 int hdr_msgidsz; /* size of msgids (in bytes) */
63 63 int hdr_msgstrsz; /* size of msgstrs (in bytes) */
64 64 int hdr_lstsz; /* size of message list (in bytes) */
65 65 } Msghdr;
66 66
67 67 typedef struct {
68 68 int lst_less;
69 69 int lst_more;
70 70 int lst_idoff;
71 71 int lst_stroff;
72 72 } Msglst;
73 73
74 74 #define LEAFINDICATOR -99
75 75 #define OLD_MSG_STRUCT_SIZE 20
76 76 #define NEW_MSG_STRUCT_SIZE (sizeof (Msglst))
77 77
78 78 /*
79 79 * Define a local structure for maintaining the domains we care about.
80 80 */
81 81 typedef struct {
82 82 const char *dom_name;
83 83 const Msghdr *dom_msghdr;
84 84 size_t dom_msgsz;
85 85 } Domain;
86 86
87 87
88 88 /*
89 89 * Perform a binary search of a message file (described by the Msghdr) for a
90 90 * msgid (string). Given a match return the associated msgstr, otherwise
91 91 * return the original msgid.
92 92 */
93 93 static const char *
94 94 msgid_to_msgstr(const Msghdr *msghdr, const char *msgid)
95 95 {
96 96 const Msglst *list, *_list;
97 97 const char *ids, *strs, *_msgid;
98 98 int off, var;
99 99
100 100 /*
101 101 * Establish pointers to the message list (we actually start the search
102 102 * in the middle of this list (hdr->midlst), the msgid strings (ids)
103 103 * and the msgstr strings (strs).
104 104 */
105 105 list = (const Msglst *)&msghdr[1];
106 106 ids = (const char *)&list[msghdr->hdr_lstcnt];
107 107 strs = (const char *)&ids[msghdr->hdr_msgidsz];
108 108
109 109 off = msghdr->hdr_midlst;
110 110
111 111 for (;;) {
112 112 _list = list + off;
113 113 _msgid = ids + _list->lst_idoff;
114 114
115 115 if ((var = strcmp(_msgid, msgid)) == 0)
116 116 return (strs + _list->lst_stroff);
117 117
118 118 if (var < 0) {
119 119 if ((off = _list->lst_less) == LEAFINDICATOR)
120 120 return (msgid);
121 121 } else {
122 122 if ((off = _list->lst_more) == LEAFINDICATOR)
123 123 return (msgid);
124 124 }
125 125 }
126 126 /* NOTREACHED */
127 127 return (NULL); /* keep gcc happy */
128 128 }
129 129
130 130 /*
131 131 * Open a message file. Following the model of setlocale(3c) we obtain the
132 132 * message file for the specified locale. Normally this is:
133 133 *
134 134 * /usr/lib/locale/`locale'/LC_MESSAGES/`domain'.mo
135 135 *
136 136 * The locale was determined during initial environment processing (see
137 137 * readenv()), which was determined from an LC_ALL, LC_MESSAGES or LANG
138 138 * setting. If no locale has been specified, or any file processing errors
139 139 * occur, internationalization is basically disabled.
140 140 */
141 141 static void
142 142 open_mofile(Domain * dom)
143 143 {
144 144 const char *domain = dom->dom_name;
145 145 char path[PATH_MAX];
146 146 int fd;
147 147 rtld_stat_t status;
148 148 const Msghdr *msghdr;
149 149 int count;
150 150 size_t size_tot, size_old, size_new;
151 151
152 152 dom->dom_msghdr = (Msghdr *)-1;
153 153
154 154 (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_FMT_MSGFILE),
155 155 glcs[CI_LCMESSAGES].lc_un.lc_ptr, domain);
156 156
157 157 if ((fd = open(path, O_RDONLY, 0)) == -1)
158 158 return;
159 159
160 160 if ((rtld_fstat(fd, &status) == -1) ||
161 161 (status.st_size < sizeof (Msghdr))) {
162 162 (void) close(fd);
163 163 return;
164 164 }
165 165
166 166 /* LINTED */
167 167 if ((msghdr = (Msghdr *)mmap(0, status.st_size, PROT_READ, MAP_SHARED,
168 168 fd, 0)) == (Msghdr *)-1) {
169 169 (void) close(fd);
170 170 return;
171 171 }
172 172 (void) close(fd);
173 173
174 174 /* checks if opened file is msg file */
175 175
176 176 count = msghdr->hdr_lstcnt;
177 177 if (((count - 1) / 2) != msghdr->hdr_midlst) {
178 178 (void) munmap((caddr_t)msghdr, status.st_size);
179 179 return;
180 180 }
181 181
182 182 size_tot = msghdr->hdr_lstsz;
183 183 size_old = OLD_MSG_STRUCT_SIZE * count;
184 184 size_new = (int)NEW_MSG_STRUCT_SIZE * count;
185 185 if ((size_tot != size_old) && (size_tot != size_new)) {
186 186 (void) munmap((caddr_t)msghdr, status.st_size);
187 187 return;
188 188 }
189 189
190 190 size_tot = msghdr->hdr_msgidsz + msghdr->hdr_msgstrsz +
191 191 (int)sizeof (Msghdr);
192 192 if ((size_tot + size_old < status.st_size) &&
193 193 (size_tot + size_new < status.st_size)) {
194 194 (void) munmap((caddr_t)msghdr, status.st_size);
195 195 return;
196 196 }
197 197
198 198 /*
199 199 * We have a good message file, initialize the Domain information.
200 200 */
201 201 dom->dom_msghdr = msghdr;
202 202 dom->dom_msgsz = status.st_size;
203 203 }
204 204
205 205
206 206 /*
207 207 * Two interfaces are established to support our internationalization.
208 208 * gettext(3i) calls originate from all link-editor libraries, and thus the
209 209 * SUNW_OST_SGS domain is assumed. dgettext() calls originate from
210 210 * dependencies such as libelf and libc.
211 211 *
212 212 * Presently we support two domains (libc's strerror() uses SUNW_OST_OSLIB).
213 213 * If ld.so.1's dependencies evolve to require more then the `domain' array
214 214 * maintained below can be enlarged or made more dynamic in nature.
215 215 */
216 216 char *
217 217 dgettext(const char *domain, const char *msgid)
218 218 {
219 219 static int domaincnt = 0;
220 220 static Domain *domains;
↓ open down ↓ |
220 lines elided |
↑ open up ↑ |
221 221 Domain *_domain;
222 222 int cnt;
223 223
224 224 if (glcs[CI_LCMESSAGES].lc_un.lc_val == 0)
225 225 return ((char *)msgid);
226 226
227 227 /*
228 228 * Determine if we've initialized any domains yet.
229 229 */
230 230 if (domaincnt == 0) {
231 - if ((domains = calloc(sizeof (Domain), 2)) == NULL)
231 + if ((domains = calloc(2, sizeof (Domain))) == NULL)
232 232 return ((char *)msgid);
233 233 domains[0].dom_name = MSG_ORIG(MSG_SUNW_OST_SGS);
234 234 domains[1].dom_name = MSG_ORIG(MSG_SUNW_OST_OSLIB);
235 235 domaincnt = 2;
236 236 }
237 237
238 238 /*
239 239 * If this is a new locale make sure we clean up any old ones.
240 240 */
241 241 if (rtld_flags & RT_FL_NEWLOCALE) {
242 242 cnt = 0;
243 243
244 244 for (_domain = domains; cnt < domaincnt; _domain++, cnt++) {
245 245 if (_domain->dom_msghdr == 0)
246 246 continue;
247 247
248 248 if (_domain->dom_msghdr != (Msghdr *)-1)
249 249 (void) munmap((caddr_t)_domain->dom_msghdr,
250 250 _domain->dom_msgsz);
251 251
252 252 _domain->dom_msghdr = 0;
253 253 }
254 254 rtld_flags &= ~RT_FL_NEWLOCALE;
255 255 }
256 256
257 257 /*
258 258 * Determine which domain we need.
259 259 */
260 260 for (cnt = 0, _domain = domains; cnt < domaincnt; _domain++, cnt++) {
261 261 if (_domain->dom_name == domain)
262 262 break;
263 263 if (strcmp(_domain->dom_name, domain) == 0)
264 264 break;
265 265 }
266 266 if (cnt == domaincnt)
267 267 return ((char *)msgid);
268 268
269 269 /*
270 270 * Determine if the domain has been initialized yet.
271 271 */
272 272 if (_domain->dom_msghdr == 0)
273 273 open_mofile(_domain);
274 274 if (_domain->dom_msghdr == (Msghdr *)-1)
275 275 return ((char *)msgid);
276 276
277 277 return ((char *)msgid_to_msgstr(_domain->dom_msghdr, msgid));
278 278 }
279 279
280 280 /*
281 281 * This satisfies any dependencies of code dragged in from libc, as we don't
282 282 * want libc's gettext implementation in ld.so.1. This routine may not be
283 283 * referenced, in which case -zignore will discard it.
284 284 */
285 285 char *
286 286 gettext(const char *msgid)
287 287 {
288 288 return ((char *)dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), msgid));
289 289 }
290 290
291 291 /*
292 292 * The sgsmsg.1l use requires the following interface.
293 293 */
294 294 const char *
295 295 _rtld_msg(Msg mid)
296 296 {
297 297 return ((char *)dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid)));
298 298 }
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX