]> git.ipfire.org Git - thirdparty/glibc.git/blame - locale/findlocale.c
Remove uses of sprintf in gen-posix-conf-vars.awk
[thirdparty/glibc.git] / locale / findlocale.c
CommitLineData
d4697bc9 1/* Copyright (C) 1996-2014 Free Software Foundation, Inc.
e4cf5070 2 This file is part of the GNU C Library.
4b10dd6c 3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
7a12c6bb 4
e4cf5070 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
7a12c6bb 9
e4cf5070
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
7a12c6bb 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
7a12c6bb 18
e7f21fa6 19#include <assert.h>
4e8f95a0 20#include <errno.h>
7a12c6bb
RM
21#include <locale.h>
22#include <stdlib.h>
23#include <string.h>
3081378b 24#include <unistd.h>
72c74375
UD
25#ifdef _POSIX_MAPPED_FILES
26# include <sys/mman.h>
27#endif
7a12c6bb
RM
28
29#include "localeinfo.h"
e7f21fa6 30#include "../iconv/gconv_charset.h"
dd9423a6 31#include "../iconv/gconv_int.h"
7a12c6bb
RM
32
33
9a411bf5
RM
34#ifdef NL_CURRENT_INDIRECT
35# define DEFINE_CATEGORY(category, category_name, items, a) \
f095bb72 36extern struct __locale_data _nl_C_##category; \
9a411bf5
RM
37weak_extern (_nl_C_##category)
38# include "categories.def"
39# undef DEFINE_CATEGORY
40
41/* Array indexed by category of pointers to _nl_C_CATEGORY slots.
42 Elements are zero for categories whose data is never used. */
f095bb72 43struct __locale_data *const _nl_C[] attribute_hidden =
9a411bf5
RM
44 {
45# define DEFINE_CATEGORY(category, category_name, items, a) \
46 [category] = &_nl_C_##category,
47# include "categories.def"
48# undef DEFINE_CATEGORY
49 };
30c14c31
RM
50#else
51# define _nl_C (_nl_C_locobj.__locales)
52#endif
7a12c6bb
RM
53
54
55/* For each category we keep a list of records for the locale files
56 which are somehow addressed. */
5746ef6f 57struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
7a12c6bb 58
cb09a2cd
RM
59const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
60
4e8f95a0
FW
61/* Checks if the name is actually present, that is, not NULL and not
62 empty. */
63static inline int
64name_present (const char *name)
65{
66 return name != NULL && name[0] != '\0';
67}
68
69/* Checks that the locale name neither extremely long, nor contains a
70 ".." path component (to prevent directory traversal). */
71static inline int
72valid_locale_name (const char *name)
73{
74 /* Not set. */
75 size_t namelen = strlen (name);
76 /* Name too long. The limit is arbitrary and prevents stack overflow
77 issues later. */
78 if (__glibc_unlikely (namelen > 255))
79 return 0;
80 /* Directory traversal attempt. */
81 static const char slashdot[4] = {'/', '.', '.', '/'};
9975e3d3
JM
82 if (__glibc_unlikely (__memmem (name, namelen,
83 slashdot, sizeof (slashdot)) != NULL))
4e8f95a0
FW
84 return 0;
85 if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
86 return 0;
87 if (namelen >= 3
88 && __glibc_unlikely (((name[0] == '.'
89 && name[1] == '.'
90 && name[2] == '/')
91 || (name[namelen - 3] == '/'
92 && name[namelen - 2] == '.'
93 && name[namelen - 1] == '.'))))
94 return 0;
95 /* If there is a slash in the name, it must start with one. */
96 if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
97 return 0;
98 return 1;
99}
7a12c6bb 100
f095bb72 101struct __locale_data *
cb09a2cd 102internal_function
7a12c6bb 103_nl_find_locale (const char *locale_path, size_t locale_path_len,
c84142e8 104 int category, const char **name)
7a12c6bb
RM
105{
106 int mask;
107 /* Name of the locale for this category. */
4e8f95a0 108 char *loc_name = (char *) *name;
7a12c6bb
RM
109 const char *language;
110 const char *modifier;
111 const char *territory;
112 const char *codeset;
113 const char *normalized_codeset;
7a12c6bb
RM
114 struct loaded_l10nfile *locale_file;
115
4e8f95a0 116 if (loc_name[0] == '\0')
7a12c6bb
RM
117 {
118 /* The user decides which locale to use by setting environment
119 variables. */
4e8f95a0
FW
120 loc_name = getenv ("LC_ALL");
121 if (!name_present (loc_name))
122 loc_name = getenv (_nl_category_names.str
9446614c 123 + _nl_category_name_idxs[category]);
4e8f95a0
FW
124 if (!name_present (loc_name))
125 loc_name = getenv ("LANG");
126 if (!name_present (loc_name))
127 loc_name = (char *) _nl_C_name;
7a12c6bb
RM
128 }
129
4e8f95a0
FW
130 /* We used to fall back to the C locale if the name contains a slash
131 character '/', but we now check for directory traversal in
132 valid_locale_name, so this is no longer necessary. */
63336471 133
4e8f95a0
FW
134 if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
135 || __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
7a12c6bb
RM
136 {
137 /* We need not load anything. The needed data is contained in
138 the library itself. */
139 *name = (char *) _nl_C_name;
140 return _nl_C[category];
141 }
4e8f95a0
FW
142 else if (!valid_locale_name (loc_name))
143 {
144 __set_errno (EINVAL);
145 return NULL;
146 }
147
148 *name = loc_name;
7a12c6bb 149
cb09a2cd
RM
150 /* We really have to load some data. First we try the archive,
151 but only if there was no LOCPATH environment variable specified. */
a1ffb40e 152 if (__glibc_likely (locale_path == NULL))
cb09a2cd 153 {
f095bb72
UD
154 struct __locale_data *data
155 = _nl_load_locale_from_archive (category, name);
a1ffb40e 156 if (__glibc_likely (data != NULL))
cb09a2cd
RM
157 return data;
158
159 /* Nothing in the archive. Set the default path to search below. */
160 locale_path = _nl_default_locale_path;
161 locale_path_len = sizeof _nl_default_locale_path;
162 }
163
7a12c6bb
RM
164 /* We really have to load some data. First see whether the name is
165 an alias. Please note that this makes it impossible to have "C"
166 or "POSIX" as aliases. */
fa0bc87c 167 loc_name = (char *) _nl_expand_alias (*name);
7a12c6bb
RM
168 if (loc_name == NULL)
169 /* It is no alias. */
c84142e8 170 loc_name = (char *) *name;
7a12c6bb
RM
171
172 /* Make a writable copy of the locale name. */
72c74375 173 loc_name = strdupa (loc_name);
7a12c6bb
RM
174
175 /* LOCALE can consist of up to four recognized parts for the XPG syntax:
176
177 language[_territory[.codeset]][@modifier]
178
7a12c6bb
RM
179 Beside the first all of them are allowed to be missing. If the
180 full specified locale is not found, the less specific one are
cb09a2cd 181 looked for. The various part will be stripped off according to
7a12c6bb 182 the following order:
e155c801
UD
183 (1) codeset
184 (2) normalized codeset
185 (3) territory
186 (4) modifier
7a12c6bb
RM
187 */
188 mask = _nl_explode_name (loc_name, &language, &modifier, &territory,
e155c801 189 &codeset, &normalized_codeset);
4f031072
UD
190 if (mask == -1)
191 /* Memory allocate problem. */
192 return NULL;
7a12c6bb
RM
193
194 /* If exactly this locale was already asked for we have an entry with
195 the complete name. */
5746ef6f 196 locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
7a12c6bb
RM
197 locale_path, locale_path_len, mask,
198 language, territory, codeset,
e155c801 199 normalized_codeset, modifier,
9446614c
UD
200 _nl_category_names.str
201 + _nl_category_name_idxs[category], 0);
7a12c6bb
RM
202
203 if (locale_file == NULL)
204 {
205 /* Find status record for addressed locale file. We have to search
206 through all directories in the locale path. */
5746ef6f 207 locale_file = _nl_make_l10nflist (&_nl_locale_file_list[category],
7a12c6bb
RM
208 locale_path, locale_path_len, mask,
209 language, territory, codeset,
e155c801 210 normalized_codeset, modifier,
9446614c
UD
211 _nl_category_names.str
212 + _nl_category_name_idxs[category], 1);
7a12c6bb
RM
213 if (locale_file == NULL)
214 /* This means we are out of core. */
215 return NULL;
216 }
7a12c6bb 217
727211c4
UD
218 /* The space for normalized_codeset is dynamically allocated. Free it. */
219 if (mask & XPG_NORM_CODESET)
220 free ((void *) normalized_codeset);
221
7a12c6bb
RM
222 if (locale_file->decided == 0)
223 _nl_load_locale (locale_file, category);
224
225 if (locale_file->data == NULL)
226 {
227 int cnt;
228 for (cnt = 0; locale_file->successor[cnt] != NULL; ++cnt)
229 {
230 if (locale_file->successor[cnt]->decided == 0)
231 _nl_load_locale (locale_file->successor[cnt], category);
232 if (locale_file->successor[cnt]->data != NULL)
233 break;
234 }
235 /* Move the entry we found (or NULL) to the first place of
236 successors. */
237 locale_file->successor[0] = locale_file->successor[cnt];
238 locale_file = locale_file->successor[cnt];
7a12c6bb 239
3a31f6f4
UD
240 if (locale_file == NULL)
241 return NULL;
242 }
7a12c6bb 243
e7f21fa6
UD
244 /* The LC_CTYPE category allows to check whether a locale is really
245 usable. If the locale name contains a charset name and the
246 charset name used in the locale (present in the LC_CTYPE data) is
247 not the same (after resolving aliases etc) we reject the locale
248 since using it would irritate users expecting the charset named
249 in the locale name. */
250 if (codeset != NULL)
251 {
252 /* Get the codeset information from the locale file. */
253 static const int codeset_idx[] =
254 {
255 [__LC_CTYPE] = _NL_ITEM_INDEX (CODESET),
256 [__LC_NUMERIC] = _NL_ITEM_INDEX (_NL_NUMERIC_CODESET),
257 [__LC_TIME] = _NL_ITEM_INDEX (_NL_TIME_CODESET),
258 [__LC_COLLATE] = _NL_ITEM_INDEX (_NL_COLLATE_CODESET),
259 [__LC_MONETARY] = _NL_ITEM_INDEX (_NL_MONETARY_CODESET),
260 [__LC_MESSAGES] = _NL_ITEM_INDEX (_NL_MESSAGES_CODESET),
261 [__LC_PAPER] = _NL_ITEM_INDEX (_NL_PAPER_CODESET),
262 [__LC_NAME] = _NL_ITEM_INDEX (_NL_NAME_CODESET),
263 [__LC_ADDRESS] = _NL_ITEM_INDEX (_NL_ADDRESS_CODESET),
264 [__LC_TELEPHONE] = _NL_ITEM_INDEX (_NL_TELEPHONE_CODESET),
265 [__LC_MEASUREMENT] = _NL_ITEM_INDEX (_NL_MEASUREMENT_CODESET),
266 [__LC_IDENTIFICATION] = _NL_ITEM_INDEX (_NL_IDENTIFICATION_CODESET)
267 };
f095bb72 268 const struct __locale_data *data;
e7f21fa6
UD
269 const char *locale_codeset;
270 char *clocale_codeset;
271 char *ccodeset;
272
f095bb72 273 data = (const struct __locale_data *) locale_file->data;
e7f21fa6
UD
274 locale_codeset =
275 (const char *) data->values[codeset_idx[category]].string;
276 assert (locale_codeset != NULL);
277 /* Note the length of the allocated memory: +3 for up to two slashes
278 and the NUL byte. */
279 clocale_codeset = (char *) alloca (strlen (locale_codeset) + 3);
280 strip (clocale_codeset, locale_codeset);
281
282 ccodeset = (char *) alloca (strlen (codeset) + 3);
283 strip (ccodeset, codeset);
284
9a018f6c
UD
285 if (__gconv_compare_alias (upstr (ccodeset, ccodeset),
286 upstr (clocale_codeset,
287 clocale_codeset)) != 0)
e7f21fa6
UD
288 /* The codesets are not identical, don't use the locale. */
289 return NULL;
290 }
291
7a12c6bb
RM
292 /* Determine the locale name for which loading succeeded. This
293 information comes from the file name. The form is
036cc82f 294 <path>/<locale>/LC_foo. We must extract the <locale> part. */
f095bb72 295 if (((const struct __locale_data *) locale_file->data)->name == NULL)
7a12c6bb 296 {
036cc82f 297 char *cp, *endp;
7a12c6bb
RM
298
299 endp = strrchr (locale_file->filename, '/');
300 cp = endp - 1;
301 while (cp[-1] != '/')
302 --cp;
f095bb72
UD
303 ((struct __locale_data *) locale_file->data)->name
304 = __strndup (cp, endp - cp);
7a12c6bb 305 }
7a12c6bb 306
323fb88d 307 /* Determine whether the user wants transliteration or not. */
5f078c32
UD
308 if (modifier != NULL
309 && __strcasecmp_l (modifier, "TRANSLIT", _nl_C_locobj_ptr) == 0)
f095bb72 310 ((struct __locale_data *) locale_file->data)->use_translit = 1;
323fb88d 311
c84142e8 312 /* Increment the usage count. */
f095bb72 313 if (((const struct __locale_data *) locale_file->data)->usage_count
a5a0310d 314 < MAX_USAGE_COUNT)
f095bb72 315 ++((struct __locale_data *) locale_file->data)->usage_count;
c84142e8 316
f095bb72 317 return (struct __locale_data *) locale_file->data;
7a12c6bb 318}
c84142e8
UD
319
320
321/* Calling this function assumes the lock for handling global locale data
322 is acquired. */
323void
cb09a2cd 324internal_function
f095bb72 325_nl_remove_locale (int locale, struct __locale_data *data)
c84142e8
UD
326{
327 if (--data->usage_count == 0)
328 {
0f283ffc 329 if (data->alloc != ld_archive)
c84142e8 330 {
0f283ffc
RM
331 /* First search the entry in the list of loaded files. */
332 struct loaded_l10nfile *ptr = _nl_locale_file_list[locale];
333
334 /* Search for the entry. It must be in the list. Otherwise it
335 is a bug and we crash badly. */
f095bb72 336 while ((struct __locale_data *) ptr->data != data)
0f283ffc
RM
337 ptr = ptr->next;
338
339 /* Mark the data as not available anymore. So when the data has
340 to be used again it is reloaded. */
341 ptr->decided = 0;
342 ptr->data = NULL;
c84142e8 343 }
c84142e8 344
0f283ffc
RM
345 /* This does the real work. */
346 _nl_unload_locale (data);
c84142e8
UD
347 }
348}