/work/workdir/UnpackedTarball/fontconfig/src/fccompat.c
Line | Count | Source (jump to first uncovered line) |
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 <stdarg.h> |
44 | | #include <stdlib.h> |
45 | | #include <string.h> |
46 | | #include <time.h> |
47 | | |
48 | | #ifdef O_CLOEXEC |
49 | 338 | # define FC_O_CLOEXEC O_CLOEXEC |
50 | | #else |
51 | | # define FC_O_CLOEXEC 0 |
52 | | #endif |
53 | | #ifdef O_LARGEFILE |
54 | 336 | # define FC_O_LARGEFILE O_LARGEFILE |
55 | | #else |
56 | | # define FC_O_LARGEFILE 0 |
57 | | #endif |
58 | | #ifdef O_BINARY |
59 | | # define FC_O_BINARY O_BINARY |
60 | | #else |
61 | | # define FC_O_BINARY 0 |
62 | | #endif |
63 | | #ifdef O_TEMPORARY |
64 | | # define FC_O_TEMPORARY O_TEMPORARY |
65 | | #else |
66 | | # define FC_O_TEMPORARY 0 |
67 | | #endif |
68 | | #ifdef O_NOINHERIT |
69 | | # define FC_O_NOINHERIT O_NOINHERIT |
70 | | #else |
71 | | # define FC_O_NOINHERIT 0 |
72 | | #endif |
73 | | |
74 | | #ifndef HAVE_UNISTD_H |
75 | | /* Values for the second argument to access. These may be OR'd together. */ |
76 | | # ifndef R_OK |
77 | | # define R_OK 4 /* Test for read permission. */ |
78 | | # endif |
79 | | # ifndef W_OK |
80 | | # define W_OK 2 /* Test for write permission. */ |
81 | | # endif |
82 | | # ifndef F_OK |
83 | | # define F_OK 0 /* Test for existence. */ |
84 | | # endif |
85 | | |
86 | | typedef int mode_t; |
87 | | #endif /* !HAVE_UNISTD_H */ |
88 | | |
89 | | #if !defined(HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S) |
90 | | static int |
91 | | mkstemp (char *template) |
92 | | { |
93 | | static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
94 | | int fd, i; |
95 | | size_t l; |
96 | | |
97 | | if (template == NULL) { |
98 | | errno = EINVAL; |
99 | | return -1; |
100 | | } |
101 | | l = strlen (template); |
102 | | if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0) { |
103 | | errno = EINVAL; |
104 | | return -1; |
105 | | } |
106 | | do { |
107 | | errno = 0; |
108 | | for (i = l - 6; i < l; i++) { |
109 | | int r = FcRandom(); |
110 | | template[i] = s[r % 62]; |
111 | | } |
112 | | fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600); |
113 | | } while (fd < 0 && errno == EEXIST); |
114 | | if (fd >= 0) |
115 | | errno = 0; |
116 | | |
117 | | return fd; |
118 | | } |
119 | | # define HAVE_MKSTEMP 1 |
120 | | #endif |
121 | | |
122 | | int |
123 | | FcOpen (const char *pathname, int flags, ...) |
124 | 336 | { |
125 | 336 | int fd = -1; |
126 | | |
127 | 336 | if (flags & O_CREAT) { |
128 | 2 | va_list ap; |
129 | 2 | mode_t mode; |
130 | | |
131 | 2 | va_start (ap, flags); |
132 | 2 | mode = (mode_t)va_arg (ap, int); |
133 | 2 | va_end (ap); |
134 | | |
135 | 2 | fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode); |
136 | 334 | } else { |
137 | 334 | fd = open (pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE); |
138 | 334 | } |
139 | | |
140 | 336 | return fd; |
141 | 336 | } |
142 | | |
143 | | int |
144 | | FcMakeTempfile (char *template) |
145 | 2 | { |
146 | 2 | int fd = -1; |
147 | | |
148 | 2 | #if HAVE_MKOSTEMP |
149 | 2 | fd = mkostemp (template, FC_O_CLOEXEC); |
150 | | #elif HAVE_MKSTEMP |
151 | | fd = mkstemp (template); |
152 | | # ifdef F_DUPFD_CLOEXEC |
153 | | if (fd != -1) { |
154 | | int newfd = fcntl (fd, F_DUPFD_CLOEXEC, STDIN_FILENO); |
155 | | |
156 | | close (fd); |
157 | | fd = newfd; |
158 | | } |
159 | | # elif defined(FD_CLOEXEC) |
160 | | if (fd != -1) { |
161 | | fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC); |
162 | | } |
163 | | # endif |
164 | | #elif HAVE__MKTEMP_S |
165 | | if (_mktemp_s (template, strlen (template) + 1) != 0) |
166 | | return -1; |
167 | | fd = FcOpen (template, O_RDWR | O_EXCL | O_CREAT, 0600); |
168 | | #endif |
169 | | |
170 | 2 | return fd; |
171 | 2 | } |
172 | | |
173 | | int32_t |
174 | | FcRandom (void) |
175 | 320 | { |
176 | 320 | int32_t result; |
177 | | |
178 | 320 | #if HAVE_RANDOM_R |
179 | 320 | static struct random_data fcrandbuf; |
180 | 320 | static char statebuf[256]; |
181 | 320 | static FcBool initialized = FcFalse; |
182 | | # ifdef _AIX |
183 | | static char *retval; |
184 | | long res; |
185 | | # endif |
186 | | |
187 | 320 | if (initialized != FcTrue) { |
188 | | # ifdef _AIX |
189 | | initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf); |
190 | | # else |
191 | 106 | initstate_r (time (NULL), statebuf, 256, &fcrandbuf); |
192 | 106 | # endif |
193 | 106 | initialized = FcTrue; |
194 | 106 | } |
195 | | |
196 | | # ifdef _AIX |
197 | | random_r (&res, &fcrandbuf); |
198 | | result = (int32_t)res; |
199 | | # else |
200 | 320 | random_r (&fcrandbuf, &result); |
201 | 320 | # endif |
202 | | #elif HAVE_RANDOM |
203 | | static char statebuf[256]; |
204 | | char *state; |
205 | | static FcBool initialized = FcFalse; |
206 | | |
207 | | if (initialized != FcTrue) { |
208 | | state = initstate (time (NULL), statebuf, 256); |
209 | | initialized = FcTrue; |
210 | | } else |
211 | | state = setstate (statebuf); |
212 | | |
213 | | result = random(); |
214 | | |
215 | | setstate (state); |
216 | | #elif HAVE_LRAND48 |
217 | | result = lrand48(); |
218 | | #elif HAVE_RAND_R |
219 | | static unsigned int seed; |
220 | | |
221 | | seed = time (NULL); |
222 | | result = rand_r (&seed); |
223 | | #elif HAVE_RAND |
224 | | static FcBool initialized = FcFalse; |
225 | | |
226 | | if (initialized != FcTrue) { |
227 | | srand (time (NULL)); |
228 | | initialized = FcTrue; |
229 | | } |
230 | | result = rand(); |
231 | | #else |
232 | | # error no random number generator function available. |
233 | | #endif |
234 | | |
235 | 320 | return result; |
236 | 320 | } |
237 | | |
238 | | #ifdef _WIN32 |
239 | | # include <direct.h> |
240 | | # define mkdir(path, mode) _mkdir (path) |
241 | | #endif |
242 | | |
243 | | FcBool |
244 | | FcMakeDirectory (const FcChar8 *dir) |
245 | 2 | { |
246 | 2 | FcChar8 *parent; |
247 | 2 | FcBool ret; |
248 | | |
249 | 2 | if (strlen ((char *)dir) == 0) |
250 | 0 | return FcFalse; |
251 | | |
252 | 2 | parent = FcStrDirname (dir); |
253 | 2 | if (!parent) |
254 | 0 | return FcFalse; |
255 | 2 | if (access ((char *)parent, F_OK) == 0) |
256 | 1 | ret = mkdir ((char *)dir, 0755) == 0 && chmod ((char *)dir, 0755) == 0; |
257 | 1 | else if (access ((char *)parent, F_OK) == -1) |
258 | 1 | ret = FcMakeDirectory (parent) && (mkdir ((char *)dir, 0755) == 0) && chmod ((char *)dir, 0755) == 0; |
259 | 0 | else |
260 | 0 | ret = FcFalse; |
261 | 2 | FcStrFree (parent); |
262 | 2 | return ret; |
263 | 2 | } |
264 | | |
265 | | ssize_t |
266 | | FcReadLink (const FcChar8 *pathname, |
267 | | FcChar8 *buf, |
268 | | size_t bufsiz) |
269 | 106 | { |
270 | 106 | #ifdef HAVE_READLINK |
271 | 106 | return readlink ((const char *)pathname, (char *)buf, bufsiz); |
272 | | #else |
273 | | /* XXX: this function is only used for FcConfigRealFilename() so far |
274 | | * and returning -1 as an error still just works. |
275 | | */ |
276 | | errno = ENOSYS; |
277 | | return -1; |
278 | | #endif |
279 | 106 | } |
280 | | |
281 | | /* On Windows MingW provides dirent.h / openddir(), but MSVC does not */ |
282 | | #ifndef HAVE_DIRENT_H |
283 | | |
284 | | struct DIR { |
285 | | struct dirent d_ent; |
286 | | HANDLE handle; |
287 | | WIN32_FIND_DATA fdata; |
288 | | FcBool valid; |
289 | | }; |
290 | | |
291 | | FcPrivate DIR * |
292 | | FcCompatOpendirWin32 (const char *dirname) |
293 | | { |
294 | | size_t len; |
295 | | char *name; |
296 | | DIR *dir; |
297 | | |
298 | | dir = calloc (1, sizeof (struct DIR)); |
299 | | if (dir == NULL) |
300 | | return NULL; |
301 | | |
302 | | len = strlen (dirname); |
303 | | name = malloc (len + 3); |
304 | | if (name == NULL) { |
305 | | free (dir); |
306 | | return NULL; |
307 | | } |
308 | | memcpy (name, dirname, len); |
309 | | name[len++] = FC_DIR_SEPARATOR; |
310 | | name[len++] = '*'; |
311 | | name[len] = '\0'; |
312 | | |
313 | | dir->handle = FindFirstFileEx (name, FindExInfoBasic, &dir->fdata, FindExSearchNameMatch, NULL, 0); |
314 | | |
315 | | free (name); |
316 | | |
317 | | if (!dir->handle) { |
318 | | free (dir); |
319 | | dir = NULL; |
320 | | |
321 | | if (GetLastError() == ERROR_FILE_NOT_FOUND) |
322 | | errno = ENOENT; |
323 | | else |
324 | | errno = EACCES; |
325 | | } |
326 | | |
327 | | dir->valid = FcTrue; |
328 | | return dir; |
329 | | } |
330 | | |
331 | | FcPrivate struct dirent * |
332 | | FcCompatReaddirWin32 (DIR *dir) |
333 | | { |
334 | | if (dir->valid != FcTrue) |
335 | | return NULL; |
336 | | |
337 | | dir->d_ent.d_name = dir->fdata.cFileName; |
338 | | |
339 | | if ((dir->fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) |
340 | | dir->d_ent.d_type = DT_DIR; |
341 | | else if (dir->fdata.dwFileAttributes == FILE_ATTRIBUTE_NORMAL) |
342 | | dir->d_ent.d_type = DT_REG; |
343 | | else |
344 | | dir->d_ent.d_type = DT_UNKNOWN; |
345 | | |
346 | | if (!FindNextFile (dir->handle, &dir->fdata)) |
347 | | dir->valid = FcFalse; |
348 | | |
349 | | return &dir->d_ent; |
350 | | } |
351 | | |
352 | | FcPrivate int |
353 | | FcCompatClosedirWin32 (DIR *dir) |
354 | | { |
355 | | if (dir != NULL && dir->handle != NULL) { |
356 | | FindClose (dir->handle); |
357 | | free (dir); |
358 | | } |
359 | | return 0; |
360 | | } |
361 | | #endif /* HAVE_DIRENT_H */ |
362 | | |
363 | | #define __fccompat__ |
364 | | #include "fcaliastail.h" |
365 | | #undef __fccompat__ |