• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *   http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <locale.h>
17 #include <string.h>
18 #include <sys/mman.h>
19 #include <stdlib.h>
20 #include "locale_impl.h"
21 #include "libc.h"
22 #include "lock.h"
23 #include "fork_impl.h"
24 
25 #define malloc __libc_malloc
26 #define calloc undef
27 #define realloc undef
28 #define free undef
29 
__lctrans_impl(const char * msg,const struct __locale_map * lm)30 const char *__lctrans_impl(const char *msg, const struct __locale_map *lm)
31 {
32 	const char *trans = 0;
33 	if (lm) trans = __mo_lookup(lm->map, lm->map_size, msg);
34 	return trans ? trans : msg;
35 }
36 
37 static const char envvars[][18] = {
38 	"LC_CTYPE",
39 	"LC_NUMERIC",
40 	"LC_TIME",
41 	"LC_COLLATE",
42 	"LC_MONETARY",
43 	"LC_MESSAGES",
44 	"LC_PAPER",
45 	"LC_NAME",
46 	"LC_ADDRESS",
47 	"LC_TELEPHONE",
48 	"LC_MEASUREMENT",
49 	"LC_IDENTIFICATION",
50 };
51 
52 volatile int __locale_lock[1];
53 volatile int *const __locale_lockptr = __locale_lock;
54 
__get_locale(int cat,const char * val)55 const struct __locale_map *__get_locale(int cat, const char *val)
56 {
57 	static void *volatile loc_head;
58 	const struct __locale_map *p;
59 	struct __locale_map *new = 0;
60 	const char *path = 0, *z;
61 	char buf[256];
62 	size_t l, n;
63 
64 	if (!*val) {
65 		(val = getenv("LC_ALL")) && *val ||
66 		(val = getenv(envvars[cat])) && *val ||
67 		(val = getenv("LANG")) && *val ||
68 		(val = "C.UTF-8");
69 	}
70 
71 	/* Limit name length and forbid leading dot or any slashes. */
72 	for (n=0; n<LOCALE_NAME_MAX && val[n] && val[n]!='/'; n++);
73 	if (val[0]=='.' || val[n]) {
74 		val = "C.UTF-8";
75 	}
76 	int builtin = (val[0]=='C' && !val[1])
77 		|| !strcmp(val, "POSIX")
78 		|| !strcmp(val, "en_US");
79 
80 	if (builtin) {
81 		if (cat == LC_CTYPE && val[1] == '.')
82 			return (void *)&__c_dot_utf8;
83 		return 0;
84 	}
85 
86 	for (p=loc_head; p; p=p->next) {
87 		if (!strcmp(val, p->name)) {
88 			return p;
89 		}
90 	}
91 
92 	if (!strcmp(val, "en_US.UTF-8") || !strcmp(val, "C.UTF-8")) {
93 		/* If no locale definition was found, make a locale map
94 		* object anyway to store the name, which is kept for the
95 		* sake of being able to do message translations at the
96 		* application level. */
97 		if (!new && (new = malloc(sizeof *new))) {
98 			new->map = __c_dot_utf8.map;
99 			new->map_size = __c_dot_utf8.map_size;
100 			memcpy(new->name, val, n);
101 			new->name[n] = 0;
102 			new->next = loc_head;
103 			new->flag = VALID;
104 			loc_head = new;
105 		}
106 	}
107 
108 	if (!libc.secure) {
109 		path = getenv("MUSL_LOCPATH");
110 	}
111 
112 	if (path) for (; *path; path=z+!!*z) {
113 		z = __strchrnul(path, ':');
114 		l = z - path;
115 		if (l >= sizeof buf - n - 2) {
116 			continue;
117 		}
118 		memcpy(buf, path, l);
119 		buf[l] = '/';
120 		memcpy(buf+l+1, val, n);
121 		buf[l+1+n] = 0;
122 		size_t map_size;
123 		const void *map = __map_file(buf, &map_size);
124 		if (map) {
125 			new = malloc(sizeof *new);
126 			if (!new) {
127 				__munmap((void *)map, map_size);
128 				break;
129 			}
130 			new->map = map;
131 			new->map_size = map_size;
132 			memcpy(new->name, val, n);
133 			new->name[n] = 0;
134 			new->next = loc_head;
135 			new->flag = VALID;
136 			loc_head = new;
137 			break;
138 		}
139 	}
140 
141 
142 	/* If no locale definition was found, make a locale map
143 	 * object anyway to store the name, which is kept for the
144 	 * sake of being able to do message translations at the
145 	 * application level. */
146 	if (!new && (new = malloc(sizeof *new))) {
147 		new->map = __c_dot_utf8.map;
148 		new->map_size = __c_dot_utf8.map_size;
149 		memcpy(new->name, val, n);
150 		new->name[n] = 0;
151 		new->next = loc_head;
152 		new->flag = INVALID;
153 		loc_head = new;
154 	}
155 
156 	/* For LC_CTYPE, never return a null pointer unless the
157 	 * requested name was "C" or "POSIX". */
158 	if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
159 
160 	return new;
161 }
162 
163