]> git.saurik.com Git - apple/cf.git/blob - CFStringDefaultEncoding.h
CF-476.15.tar.gz
[apple/cf.git] / CFStringDefaultEncoding.h
1 /*
2 * Copyright (c) 2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /* CFStringDefaultEncoding.h
24 Copyright (c) 1998-2007, Apple Inc. All rights reserved.
25 */
26
27 #if !defined(__COREFOUNDATION_CFSTRINGDEFAULTENCODING__)
28 #define __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ 1
29
30 /* This file defines static inline functions used both by CarbonCore & CF. */
31
32 #include <CoreFoundation/CFBase.h>
33
34 #if defined(__MACH__)
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <pwd.h>
38 #include <sys/param.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <xlocale.h>
43
44 CF_EXTERN_C_BEGIN
45
46 #define __kCFUserEncodingEnvVariableName ("__CF_USER_TEXT_ENCODING")
47 #define __kCFMaxDefaultEncodingFileLength (24)
48 #define __kCFUserEncodingFileName ("/.CFUserTextEncoding")
49
50 /* This function is used to obtain users' default script/region code.
51 The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory.
52 */
53 CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) {
54 char *stringValue;
55 char buffer[__kCFMaxDefaultEncodingFileLength];
56 int uid = getuid();
57
58 if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) {
59 if ((uid == strtol_l(stringValue, &stringValue, 0, NULL)) && (':' == *stringValue)) {
60 ++stringValue;
61 } else {
62 stringValue = NULL;
63 }
64 }
65
66 if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) {
67 struct passwd *passwdp;
68
69 if ((passwdp = getpwuid((uid_t)uid))) {
70 char filename[MAXPATHLEN + 1];
71
72 const char *path = NULL;
73 if (!issetugid()) {
74 path = getenv("CFFIXED_USER_HOME");
75 }
76 if (!path) {
77 path = passwdp->pw_dir;
78 }
79
80 strlcpy(filename, path, sizeof(filename));
81 strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
82
83 int no_hang_fd = open("/dev/autofs_nowait", 0);
84 int fd = open(filename, O_RDONLY, 0);
85 if (fd == -1) {
86 // Cannot open the file. Let's fallback to smRoman/verUS
87 snprintf(filename, sizeof(filename), "0x%X:0:0", uid);
88 setenv(__kCFUserEncodingEnvVariableName, filename, 1);
89 } else {
90 int readSize;
91
92 // cjk: We do not turn on F_NOCACHE on the fd here, because
93 // many processes read this file on startup, and caching the
94 // is probably a good thing, for the system as a whole.
95 readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
96 buffer[(readSize < 0 ? 0 : readSize)] = '\0';
97 close(fd);
98 stringValue = buffer;
99
100 // Well, we already have a buffer, let's reuse it
101 snprintf(filename, sizeof(filename), "0x%X:%s", uid, buffer);
102 setenv(__kCFUserEncodingEnvVariableName, filename, 1);
103 }
104 close(no_hang_fd);
105 }
106 }
107
108 if (stringValue) {
109 *oScriptValue = strtol_l(stringValue, &stringValue, 0, NULL);
110 if (*stringValue == ':') {
111 if (oRegionValue) *oRegionValue = strtol_l(++stringValue, NULL, 0, NULL);
112 return;
113 }
114 }
115
116 // Falling back
117 *oScriptValue = 0; // smRoman
118 if (oRegionValue) *oRegionValue = 0; // verUS
119 }
120
121 CF_INLINE uint32_t __CFStringGetInstallationRegion() {
122 char *stringValue = NULL;
123 char buffer[__kCFMaxDefaultEncodingFileLength];
124 struct passwd *passwdp;
125
126 if ((passwdp = getpwuid((uid_t)0))) {
127 char filename[MAXPATHLEN + 1];
128
129 const char *path = NULL;
130 if (!issetugid()) {
131 path = getenv("CFFIXED_USER_HOME");
132 }
133 if (!path) {
134 path = passwdp->pw_dir;
135 }
136
137 strlcpy(filename, path, sizeof(filename));
138 strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
139
140 int no_hang_fd = open("/dev/autofs_nowait", 0);
141 int fd = open(filename, O_RDONLY, 0);
142 if (fd == -1) {
143 int readSize;
144
145 // cjk: We do not turn on F_NOCACHE on the fd here, because
146 // many processes read this file on startup, and caching the
147 // is probably a good thing, for the system as a whole.
148 readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
149 buffer[(readSize < 0 ? 0 : readSize)] = '\0';
150 close(fd);
151 stringValue = buffer;
152 }
153 close(no_hang_fd);
154 }
155
156 if (stringValue) {
157 (void)strtol_l(stringValue, &stringValue, 0, NULL);
158 if (*stringValue == ':') return strtol_l(++stringValue, NULL, 0, NULL);
159 }
160
161 return 0; // verUS
162 }
163
164 CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) {
165 char *stringValue = NULL;
166 char buffer[__kCFMaxDefaultEncodingFileLength];
167 struct passwd *passwdp;
168
169 *encoding = 0; *region = 0;
170
171 if ((passwdp = getpwuid((uid_t)0))) {
172 char filename[MAXPATHLEN + 1];
173
174 const char *path = NULL;
175 if (!issetugid()) {
176 path = getenv("CFFIXED_USER_HOME");
177 }
178 if (!path) {
179 path = passwdp->pw_dir;
180 }
181
182 strlcpy(filename, path, sizeof(filename));
183 strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
184
185 int no_hang_fd = open("/dev/autofs_nowait", 0);
186 int fd = open(filename, O_RDONLY, 0);
187 if (fd == -1) {
188 int readSize;
189
190 readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
191 buffer[(readSize < 0 ? 0 : readSize)] = '\0';
192 close(fd);
193 stringValue = buffer;
194 }
195 close(no_hang_fd);
196 }
197
198 if (stringValue) {
199 *encoding = strtol_l(stringValue, &stringValue, 0, NULL);
200 if (*stringValue == ':') *region = strtol_l(++stringValue, NULL, 0, NULL);
201 }
202 }
203
204 CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) {
205 struct passwd *passwdp;
206
207 if ((passwdp = getpwuid(getuid()))) {
208 char filename[MAXPATHLEN + 1];
209
210 const char *path = NULL;
211 if (!issetugid()) {
212 path = getenv("CFFIXED_USER_HOME");
213 }
214 if (!path) {
215 path = passwdp->pw_dir;
216 }
217
218 strlcpy(filename, path, sizeof(filename));
219 strlcat(filename, __kCFUserEncodingFileName, sizeof(filename));
220
221 int no_hang_fd = open("/dev/autofs_nowait", 0);
222 (void)unlink(filename); // In case, file exists
223 int fd = open(filename, O_WRONLY|O_CREAT, 0400);
224 if (fd == -1) {
225 char buffer[__kCFMaxDefaultEncodingFileLength];
226 unsigned int writeSize;
227
228 writeSize = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue);
229 (void)write(fd, buffer, (writeSize > __kCFMaxDefaultEncodingFileLength ? __kCFMaxDefaultEncodingFileLength : writeSize));
230 close(fd);
231 }
232 close(no_hang_fd);
233 }
234 }
235
236 CF_EXTERN_C_END
237
238 #endif
239
240 #endif /* ! __COREFOUNDATION_CFSTRINGDEFAULTENCODING__ */
241