1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <assert.h>
22: #include <errno.h>
23: #include <fcntl.h>
24: #include <locale.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
28: #ifdef _POSIX_MAPPED_FILES
29: # include <sys/mman.h>
30: #endif
31: #include <sys/stat.h>
32:
33: #include <not-cancel.h>
34: #include "localeinfo.h"
35:
36:
37: static const size_t _nl_category_num_items[] =
38: {
39: #define DEFINE_CATEGORY(category, category_name, items, a) \
40: [category] = _NL_ITEM_INDEX (_NL_NUM_##category),
41: #include "categories.def"
42: #undef DEFINE_CATEGORY
43: };
44:
45:
46: #define NO_PAREN(arg, rest...) arg, ##rest
47:
48: #define DEFINE_CATEGORY(category, category_name, items, a) \
49: static const enum value_type _nl_value_type_##category[] = { NO_PAREN items };
50: #define DEFINE_ELEMENT(element, element_name, optstd, type, rest...) \
51: [_NL_ITEM_INDEX (element)] = type,
52: #include "categories.def"
53: #undef DEFINE_CATEGORY
54:
55: static const enum value_type *const _nl_value_types[] =
56: {
57: #define DEFINE_CATEGORY(category, category_name, items, a) \
58: [category] = _nl_value_type_##category,
59: #include "categories.def"
60: #undef DEFINE_CATEGORY
61: };
62:
63:
64: struct locale_data *
65: internal_function
66: _nl_intern_locale_data (int category, const void *data, size_t datasize)
67: {
68: const struct
69: {
70: unsigned int magic;
71: unsigned int nstrings;
72: unsigned int strindex[0];
73: } *const filedata = data;
74: struct locale_data *newdata;
75: size_t cnt;
76:
77: if (__builtin_expect (datasize < sizeof *filedata, 0)
78: || __builtin_expect (filedata->magic != LIMAGIC (category), 0))
79: {
80:
81: __set_errno (EINVAL);
82: return NULL;
83: }
84:
85: if (__builtin_expect (filedata->nstrings < _nl_category_num_items[category],
86: 0)
87: || (__builtin_expect (sizeof *filedata
88: + filedata->nstrings * sizeof (unsigned int)
89: >= datasize, 0)))
90: {
91:
92: __set_errno (EINVAL);
93: return NULL;
94: }
95:
96: newdata = malloc (sizeof *newdata
97: + filedata->nstrings * sizeof (union locale_data_value));
98: if (newdata == NULL)
99: return NULL;
100:
101: newdata->filedata = (void *) filedata;
102: newdata->filesize = datasize;
103: newdata->private.data = NULL;
104: newdata->private.cleanup = NULL;
105: newdata->usage_count = 0;
106: newdata->use_translit = 0;
107: newdata->nstrings = filedata->nstrings;
108: for (cnt = 0; cnt < newdata->nstrings; ++cnt)
109: {
110: size_t idx = filedata->strindex[cnt];
111: if (__builtin_expect (idx > (size_t) newdata->filesize, 0))
112: {
113: puntdata:
114: free (newdata);
115: __set_errno (EINVAL);
116: return NULL;
117: }
118:
119:
120:
121:
122: switch (category)
123: {
124: #define CATTEST(cat) \
125: case LC_##cat: \
126: assert (cnt < (sizeof (_nl_value_type_LC_##cat) \
127: / sizeof (_nl_value_type_LC_##cat[0]))); \
128: break
129: CATTEST (NUMERIC);
130: CATTEST (TIME);
131: CATTEST (COLLATE);
132: CATTEST (MONETARY);
133: CATTEST (MESSAGES);
134: CATTEST (PAPER);
135: CATTEST (NAME);
136: CATTEST (ADDRESS);
137: CATTEST (TELEPHONE);
138: CATTEST (MEASUREMENT);
139: CATTEST (IDENTIFICATION);
140: default:
141: assert (category == LC_CTYPE);
142: break;
143: }
144:
145: if ((category == LC_CTYPE
146: && cnt >= (sizeof (_nl_value_type_LC_CTYPE)
147: / sizeof (_nl_value_type_LC_CTYPE[0])))
148: || __builtin_expect (_nl_value_types[category][cnt] != word, 1))
149: newdata->values[cnt].string = newdata->filedata + idx;
150: else
151: {
152: if (idx % __alignof__ (u_int32_t) != 0)
153: goto puntdata;
154: newdata->values[cnt].word =
155: *((const u_int32_t *) (newdata->filedata + idx));
156: }
157: }
158:
159: return newdata;
160: }
161:
162: void
163: internal_function
164: _nl_load_locale (struct loaded_l10nfile *file, int category)
165: {
166: int fd;
167: void *filedata;
168: struct stat64 st;
169: struct locale_data *newdata;
170: int save_err;
171: int alloc = ld_mapped;
172:
173: file->decided = 1;
174: file->data = NULL;
175:
176: fd = open_not_cancel_2 (file->filename, O_RDONLY);
177: if (__builtin_expect (fd, 0) < 0)
178:
179: return;
180:
181: if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
182: {
183: puntfd:
184: close_not_cancel_no_status (fd);
185: return;
186: }
187: if (__builtin_expect (S_ISDIR (st.st_mode), 0))
188: {
189:
190:
191: char *newp;
192: size_t filenamelen;
193:
194: close_not_cancel_no_status (fd);
195:
196: filenamelen = strlen (file->filename);
197: newp = (char *) alloca (filenamelen
198: + 5 + _nl_category_name_sizes[category] + 1);
199: __mempcpy (__mempcpy (__mempcpy (newp, file->filename, filenamelen),
200: "/SYS_", 5),
201: _nl_category_names.str + _nl_category_name_idxs[category],
202: _nl_category_name_sizes[category] + 1);
203:
204: fd = open_not_cancel_2 (newp, O_RDONLY);
205: if (__builtin_expect (fd, 0) < 0)
206: return;
207:
208: if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st), 0) < 0)
209: goto puntfd;
210: }
211:
212:
213: save_err = errno;
214: #ifdef _POSIX_MAPPED_FILES
215: # ifndef MAP_COPY
216:
217: # define MAP_COPY MAP_PRIVATE
218: # endif
219: # ifndef MAP_FILE
220:
221: # define MAP_FILE 0
222: # endif
223: filedata = __mmap ((caddr_t) 0, st.st_size,
224: PROT_READ, MAP_FILE|MAP_COPY, fd, 0);
225: if (__builtin_expect (filedata == MAP_FAILED, 0))
226: {
227: if (__builtin_expect (errno, ENOSYS) == ENOSYS)
228: {
229: #endif
230:
231: alloc = ld_malloced;
232: filedata = malloc (st.st_size);
233: if (filedata != NULL)
234: {
235: off_t to_read = st.st_size;
236: ssize_t nread;
237: char *p = (char *) filedata;
238: while (to_read > 0)
239: {
240: nread = read_not_cancel (fd, p, to_read);
241: if (__builtin_expect (nread, 1) <= 0)
242: {
243: free (filedata);
244: if (nread == 0)
245: __set_errno (EINVAL);
246: goto puntfd;
247: }
248: p += nread;
249: to_read -= nread;
250: }
251: __set_errno (save_err);
252: }
253: #ifdef _POSIX_MAPPED_FILES
254: }
255: }
256: #endif
257:
258:
259: close_not_cancel_no_status (fd);
260:
261: if (__builtin_expect (filedata == NULL, 0))
262:
263: return;
264:
265: newdata = _nl_intern_locale_data (category, filedata, st.st_size);
266: if (__builtin_expect (newdata == NULL, 0))
267:
268: {
269: #ifdef _POSIX_MAPPED_FILES
270: if (alloc == ld_mapped)
271: __munmap ((caddr_t) filedata, st.st_size);
272: #endif
273: return;
274: }
275:
276:
277: newdata->name = NULL;
278: newdata->alloc = alloc;
279:
280: file->data = newdata;
281: }
282:
283: void
284: internal_function
285: _nl_unload_locale (struct locale_data *locale)
286: {
287: if (locale->private.cleanup)
288: (*locale->private.cleanup) (locale);
289:
290: switch (__builtin_expect (locale->alloc, ld_mapped))
291: {
292: case ld_malloced:
293: free ((void *) locale->filedata);
294: break;
295: case ld_mapped:
296: #ifdef _POSIX_MAPPED_FILES
297: __munmap ((caddr_t) locale->filedata, locale->filesize);
298: break;
299: #endif
300: case ld_archive:
301: break;
302: }
303:
304: if (__builtin_expect (locale->alloc, ld_mapped) != ld_archive)
305: free ((char *) locale->name);
306:
307: free (locale);
308: }