/work/workdir/UnpackedTarball/fontconfig/src/fccompat.c
Line | Count | Source |
1 | | /* |
2 | | * fontconfig/src/fccompat.c |
3 | | * |
4 | | * Copyright © 2012 Red Hat, Inc. |
5 | | * |
6 | | * Author(s): |
7 | | * Akira TAGOH |
8 | | * |
9 | | * Permission to use, copy, modify, distribute, and sell this software and its |
10 | | * documentation for any purpose is hereby granted without fee, provided that |
11 | | * the above copyright notice appear in all copies and that both that |
12 | | * copyright notice and this permission notice appear in supporting |
13 | | * documentation, and that the name of the author(s) not be used in |
14 | | * advertising or publicity pertaining to distribution of the software without |
15 | | * specific, written prior permission. The authors make no |
16 | | * representations about the suitability of this software for any purpose. It |
17 | | * is provided "as is" without express or implied warranty. |
18 | | * |
19 | | * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
20 | | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
21 | | * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
22 | | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
23 | | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
24 | | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
25 | | * PERFORMANCE OF THIS SOFTWARE. |
26 | | */ |
27 | | |
28 | | #include "fcint.h" |
29 | | |
30 | | #include <errno.h> |
31 | | #if HAVE_SYS_TYPES_H |
32 | | # include <sys/types.h> |
33 | | #endif |
34 | | #if HAVE_SYS_STAT_H |
35 | | # include <sys/stat.h> |
36 | | #endif |
37 | | #if HAVE_FCNTL_H |
38 | | # include <fcntl.h> |
39 | | #endif |
40 | | #if HAVE_UNISTD_H |
41 | | # include <unistd.h> |
42 | | #endif |
43 | | #include <locale.h> |
44 | | #include <stdarg.h> |
45 | | #include <stdlib.h> |
46 | | #include <string.h> |
47 | | #include <time.h> |
48 | | |
49 | | #ifdef O_CLOEXEC |
50 | 340 | # define FC_O_CLOEXEC O_CLOEXEC |
51 | | #else |
52 | | # define FC_O_CLOEXEC 0 |
53 | | #endif |
54 | | #ifdef O_LARGEFILE |
55 | 338 | # define FC_O_LARGEFILE O_LARGEFILE |
56 | | #else |
57 | | # define FC_O_LARGEFILE 0 |
58 | | #endif |
59 | | #ifdef O_BINARY |
60 | | # define FC_O_BINARY O_BINARY |
61 | | #else |
62 | | # define FC_O_BINARY 0 |
63 | | #endif |
64 | | #ifdef O_TEMPORARY |
65 | | # define FC_O_TEMPORARY O_TEMPORARY |
66 | | #else |
67 | | # define FC_O_TEMPORARY 0 |
68 | | #endif |
69 | | #ifdef O_NOINHERIT |
70 | | # define FC_O_NOINHERIT O_NOINHERIT |
71 | | #else |
72 | | # define FC_O_NOINHERIT 0 |
73 | | #endif |
74 | | |
75 | | #ifndef HAVE_UNISTD_H |
76 | | /* Values for the second argument to access. These may be OR'd together. */ |
77 | | # ifndef R_OK |
78 | | # define R_OK 4 /* Test for read permission. */ |
79 | | # endif |
80 | | # ifndef W_OK |
81 | | # define W_OK 2 /* Test for write permission. */ |
82 | | # endif |
83 | | # ifndef F_OK |
84 | | # define F_OK 0 /* Test for existence. */ |
85 | | # endif |
86 | | |
87 | | typedef int mode_t; |
88 | | #endif /* !HAVE_UNISTD_H */ |
89 | | |
90 | | #if !defined(HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S) |
91 | | static int |
92 | | mkstemp (char *template) |
93 | | { |
94 | | static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
95 | | int fd, i; |
96 | | size_t l; |
97 | | |
98 | | if (template == NULL) { |
99 | | errno = EINVAL; |
100 | | return -1; |
101 | | } |
102 | | l = strlen (template); |
103 | | if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0) { |
104 | | errno = EINVAL; |
105 | | return -1; |
106 | | } |
107 | | do { |
108 | | errno = 0; |
109 | | for (i = l - 6; i < l; i++) { |
110 | | int r = FcRandom(); |
111 | | template[i] = s[r % 62]; |
112 | | } |
113 | | fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600); |
114 | | } while (fd < 0 && errno == EEXIST); |
115 | | if (fd >= 0) |
116 | | errno = 0; |
117 | | |
118 | | return fd; |
119 | | } |
120 | | # define HAVE_MKSTEMP 1 |
121 | | #endif |
122 | | |
123 | | int |
124 | | FcOpen (const char *pathname, int flags, ...) |
125 | 338 | { |
126 | 338 | int fd = -1; |
127 | | |
128 | 338 | if (flags & O_CREAT) { |
129 | 2 | va_list ap; |
130 | 2 | mode_t mode; |
131 | | |
132 | 2 | va_start (ap, flags); |
133 | 2 | mode = (mode_t)va_arg (ap, int); |
134 | 2 | va_end (ap); |
135 | | |
136 | 2 | fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode); |
137 | 336 | } else { |
138 | 336 | fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE); |
139 | 336 | } |
140 | | |
141 | 338 | return fd; |
142 | 338 | } |
143 | | |
144 | | int |
145 | | FcMakeTempfile (char *template) |
146 | 2 | { |
147 | 2 | int fd = -1; |
148 | | |
149 | 2 | #if HAVE_MKOSTEMP |
150 | 2 | fd = mkostemp (template, FC_O_CLOEXEC); |
151 | | #elif HAVE_MKSTEMP |
152 | | fd = mkstemp (template); |
153 | | # ifdef F_DUPFD_CLOEXEC |
154 | | if (fd != -1) { |
155 | | int newfd = fcntl (fd, F_DUPFD_CLOEXEC, STDIN_FILENO); |
156 | | |
157 | | close (fd); |
158 | | fd = newfd; |
159 | | } |
160 | | # elif defined(FD_CLOEXEC) |
161 | | if (fd != -1) { |
162 | | fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC); |
163 | | } |
164 | | # endif |
165 | | #elif HAVE__MKTEMP_S |
166 | | if (_mktemp_s (template, strlen (template) + 1) != 0) |
167 | | return -1; |
168 | | fd = FcOpen (template, O_RDWR | O_EXCL | O_CREAT, 0600); |
169 | | #endif |
170 | | |
171 | 2 | return fd; |
172 | 2 | } |
173 | | |
174 | | int32_t |
175 | | FcRandom (void) |
176 | 320 | { |
177 | 320 | int32_t result; |
178 | | |
179 | 320 | #if HAVE_RANDOM_R |
180 | 320 | static struct random_data fcrandbuf; |
181 | 320 | static char statebuf[256]; |
182 | 320 | static FcBool initialized = FcFalse; |
183 | | # ifdef _AIX |
184 | | static char *retval; |
185 | | long res; |
186 | | # endif |
187 | | |
188 | 320 | if (initialized != FcTrue) { |
189 | | # ifdef _AIX |
190 | | initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf); |
191 | | # else |
192 | 106 | initstate_r (time (NULL), statebuf, 256, &fcrandbuf); |
193 | 106 | # endif |
194 | 106 | initialized = FcTrue; |
195 | 106 | } |
196 | | |
197 | | # ifdef _AIX |
198 | | random_r (&res, &fcrandbuf); |
199 | | result = (int32_t)res; |
200 | | # else |
201 | 320 | random_r (&fcrandbuf, &result); |
202 | 320 | # endif |
203 | | #elif HAVE_RANDOM |
204 | | static char statebuf[256]; |
205 | | char *state; |
206 | | static FcBool initialized = FcFalse; |
207 | | |
208 | | if (initialized != FcTrue) { |
209 | | state = initstate (time (NULL), statebuf, 256); |
210 | | initialized = FcTrue; |
211 | | } else |
212 | | state = setstate (statebuf); |
213 | | |
214 | | result = random(); |
215 | | |
216 | | setstate (state); |
217 | | #elif HAVE_LRAND48 |
218 | | result = lrand48(); |
219 | | #elif HAVE_RAND_R |
220 | | static unsigned int seed; |
221 | | |
222 | | seed = time (NULL); |
223 | | result = rand_r (&seed); |
224 | | #elif HAVE_RAND |
225 | | static FcBool initialized = FcFalse; |
226 | | |
227 | | if (initialized != FcTrue) { |
228 | | srand (time (NULL)); |
229 | | initialized = FcTrue; |
230 | | } |
231 | | result = rand(); |
232 | | #else |
233 | | # error no random number generator function available. |
234 | | #endif |
235 | | |
236 | 320 | return result; |
237 | 320 | } |
238 | | |
239 | | #ifdef _WIN32 |
240 | | # include <direct.h> |
241 | | # define mkdir(path, mode) _mkdir (path) |
242 | | #endif |
243 | | |
244 | | FcBool |
245 | | FcMakeDirectory (const FcChar8 *dir) |
246 | 2 | { |
247 | 2 | FcChar8 *parent; |
248 | 2 | FcBool ret; |
249 | | |
250 | 2 | if (strlen ((char *)dir) == 0) |
251 | 0 | return FcFalse; |
252 | | |
253 | 2 | parent = FcStrDirname (dir); |
254 | 2 | if (!parent) |
255 | 0 | return FcFalse; |
256 | 2 | if (access ((char *)parent, F_OK) == 0) |
257 | 1 | ret = mkdir ((char *)dir, 0755) == 0 && chmod ((char *)dir, 0755) == 0; |
258 | 1 | else if (access ((char *)parent, F_OK) == -1) |
259 | 1 | ret = FcMakeDirectory (parent) && (mkdir ((char *)dir, 0755) == 0) && chmod ((char *)dir, 0755) == 0; |
260 | 0 | else |
261 | 0 | ret = FcFalse; |
262 | 2 | FcStrFree (parent); |
263 | 2 | return ret; |
264 | 2 | } |
265 | | |
266 | | ssize_t |
267 | | FcReadLink (const FcChar8 *pathname, |
268 | | FcChar8 *buf, |
269 | | size_t bufsiz) |
270 | 106 | { |
271 | 106 | #ifdef HAVE_READLINK |
272 | 106 | return readlink ((const char *)pathname, (char *)buf, bufsiz); |
273 | | #else |
274 | | /* XXX: this function is only used for FcConfigRealFilename() so far |
275 | | * and returning -1 as an error still just works. |
276 | | */ |
277 | | errno = ENOSYS; |
278 | | return -1; |
279 | | #endif |
280 | 106 | } |
281 | | |
282 | | /* On Windows MingW provides dirent.h / openddir(), but MSVC does not */ |
283 | | #ifndef HAVE_DIRENT_H |
284 | | |
285 | | struct DIR { |
286 | | struct dirent d_ent; |
287 | | HANDLE handle; |
288 | | WIN32_FIND_DATA fdata; |
289 | | FcBool valid; |
290 | | }; |
291 | | |
292 | | FcPrivate DIR * |
293 | | FcCompatOpendirWin32 (const char *dirname) |
294 | | { |
295 | | size_t len; |
296 | | char *name; |
297 | | DIR *dir; |
298 | | |
299 | | dir = calloc (1, sizeof (struct DIR)); |
300 | | if (dir == NULL) |
301 | | return NULL; |
302 | | |
303 | | len = strlen (dirname); |
304 | | name = malloc (len + 3); |
305 | | if (name == NULL) { |
306 | | free (dir); |
307 | | return NULL; |
308 | | } |
309 | | memcpy (name, dirname, len); |
310 | | name[len++] = FC_DIR_SEPARATOR; |
311 | | name[len++] = '*'; |
312 | | name[len] = '\0'; |
313 | | |
314 | | dir->handle = FindFirstFileEx (name, FindExInfoBasic, &dir->fdata, FindExSearchNameMatch, NULL, 0); |
315 | | |
316 | | free (name); |
317 | | |
318 | | if (!dir->handle) { |
319 | | free (dir); |
320 | | dir = NULL; |
321 | | |
322 | | if (GetLastError() == ERROR_FILE_NOT_FOUND) |
323 | | errno = ENOENT; |
324 | | else |
325 | | errno = EACCES; |
326 | | } |
327 | | |
328 | | dir->valid = FcTrue; |
329 | | return dir; |
330 | | } |
331 | | |
332 | | FcPrivate struct dirent * |
333 | | FcCompatReaddirWin32 (DIR *dir) |
334 | | { |
335 | | if (dir->valid != FcTrue) |
336 | | return NULL; |
337 | | |
338 | | dir->d_ent.d_name = dir->fdata.cFileName; |
339 | | |
340 | | if ((dir->fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) |
341 | | dir->d_ent.d_type = DT_DIR; |
342 | | else if (dir->fdata.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) |
343 | | dir->d_ent.d_type = DT_REG; |
344 | | else |
345 | | dir->d_ent.d_type = DT_UNKNOWN; |
346 | | |
347 | | if (!FindNextFile (dir->handle, &dir->fdata)) |
348 | | dir->valid = FcFalse; |
349 | | |
350 | | return &dir->d_ent; |
351 | | } |
352 | | |
353 | | FcPrivate int |
354 | | FcCompatClosedirWin32 (DIR *dir) |
355 | | { |
356 | | if (dir != NULL && dir->handle != NULL) { |
357 | | FindClose (dir->handle); |
358 | | free (dir); |
359 | | } |
360 | | return 0; |
361 | | } |
362 | | #endif /* HAVE_DIRENT_H */ |
363 | | |
364 | | FcLocale |
365 | | FcLocaleCreate (FcLocaleMask mask, const char *locale) |
366 | 0 | { |
367 | | #ifdef _WIN32 |
368 | | return _create_locale (mask, locale); |
369 | | #else |
370 | 0 | return newlocale (mask, locale, (locale_t)0); |
371 | 0 | #endif |
372 | 0 | } |
373 | | |
374 | | #ifndef _WIN32 |
375 | | FcLocale |
376 | | FcLocaleSetCurrent (FcLocale loc) |
377 | 0 | { |
378 | 0 | return uselocale (loc); |
379 | 0 | } |
380 | | #endif |
381 | | |
382 | | void |
383 | | FcLocaleDestroy (FcLocale locale) |
384 | 0 | { |
385 | | #ifdef _WIN32 |
386 | | _free_locale (locale); |
387 | | #else |
388 | 0 | freelocale (locale); |
389 | 0 | #endif |
390 | 0 | } |
391 | | |
392 | | #define __fccompat__ |
393 | | #include "fcaliastail.h" |
394 | | #undef __fccompat__ |