Imported Upstream version 2.13.0
[platform/upstream/fontconfig.git] / src / fccompat.c
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 #define FC_O_CLOEXEC O_CLOEXEC
50 #else
51 #define FC_O_CLOEXEC 0
52 #endif
53 #ifdef O_LARGEFILE
54 #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 #if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
75 static int
76 mkstemp (char *template)
77 {
78     static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
79     int fd, i;
80     size_t l;
81
82     if (template == NULL)
83     {
84         errno = EINVAL;
85         return -1;
86     }
87     l = strlen (template);
88     if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
89     {
90         errno = EINVAL;
91         return -1;
92     }
93     do
94     {
95         errno = 0;
96         for (i = l - 6; i < l; i++)
97         {
98             int r = FcRandom ();
99             template[i] = s[r % 62];
100         }
101         fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
102     } while (fd < 0 && errno == EEXIST);
103     if (fd >= 0)
104         errno = 0;
105
106     return fd;
107 }
108 #define HAVE_MKSTEMP 1
109 #endif
110
111 int
112 FcOpen(const char *pathname, int flags, ...)
113 {
114     int fd = -1;
115
116     if (flags & O_CREAT)
117     {
118         va_list ap;
119         mode_t mode;
120
121         va_start(ap, flags);
122         mode = (mode_t) va_arg(ap, int);
123         va_end(ap);
124
125         fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
126     }
127     else
128     {
129         fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
130     }
131
132     return fd;
133 }
134
135 int
136 FcMakeTempfile (char *template)
137 {
138     int fd = -1;
139
140 #if HAVE_MKOSTEMP
141     fd = mkostemp (template, FC_O_CLOEXEC);
142 #elif HAVE_MKSTEMP
143     fd = mkstemp (template);
144 #  ifdef F_DUPFD_CLOEXEC
145     if (fd != -1)
146     {
147         int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
148
149         close(fd);
150         fd = newfd;
151     }
152 #  elif defined(FD_CLOEXEC)
153     if (fd != -1)
154     {
155         fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
156     }
157 #  endif
158 #elif HAVE__MKTEMP_S
159    if (_mktemp_s(template, strlen(template) + 1) != 0)
160        return -1;
161    fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
162 #endif
163
164     return fd;
165 }
166
167 int32_t
168 FcRandom(void)
169 {
170     int32_t result;
171
172 #if HAVE_RANDOM_R
173     static struct random_data fcrandbuf;
174     static char statebuf[256];
175     static FcBool initialized = FcFalse;
176 #ifdef _AIX
177     static char *retval;
178     long res;
179 #endif
180
181     if (initialized != FcTrue)
182     {
183 #ifdef _AIX
184         initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf);
185 #else
186         initstate_r (time (NULL), statebuf, 256, &fcrandbuf);
187 #endif
188         initialized = FcTrue;
189     }
190
191 #ifdef _AIX
192     random_r (&res, &fcrandbuf);
193     result = (int32_t)res;
194 #else
195     random_r (&fcrandbuf, &result);
196 #endif
197 #elif HAVE_RANDOM
198     static char statebuf[256];
199     char *state;
200     static FcBool initialized = FcFalse;
201
202     if (initialized != FcTrue)
203     {
204         state = initstate (time (NULL), statebuf, 256);
205         initialized = FcTrue;
206     }
207     else
208         state = setstate (statebuf);
209
210     result = random ();
211
212     setstate (state);
213 #elif HAVE_LRAND48
214     result = lrand48 ();
215 #elif HAVE_RAND_R
216     static unsigned int seed = time (NULL);
217
218     result = rand_r (&seed);
219 #elif HAVE_RAND
220     static FcBool initialized = FcFalse;
221
222     if (initialized != FcTrue)
223     {
224         srand (time (NULL));
225         initialized = FcTrue;
226     }
227     result = rand ();
228 #else
229 # error no random number generator function available.
230 #endif
231
232     return result;
233 }
234
235 #ifdef _WIN32
236 #include <direct.h>
237 #define mkdir(path,mode) _mkdir(path)
238 #endif
239
240 FcBool
241 FcMakeDirectory (const FcChar8 *dir)
242 {
243     FcChar8 *parent;
244     FcBool  ret;
245
246     if (strlen ((char *) dir) == 0)
247         return FcFalse;
248
249     parent = FcStrDirname (dir);
250     if (!parent)
251         return FcFalse;
252     if (access ((char *) parent, F_OK) == 0)
253         ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
254     else if (access ((char *) parent, F_OK) == -1)
255         ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
256     else
257         ret = FcFalse;
258     FcStrFree (parent);
259     return ret;
260 }
261
262 ssize_t
263 FcReadLink (const FcChar8 *pathname,
264             FcChar8       *buf,
265             size_t         bufsiz)
266 {
267 #ifdef HAVE_READLINK
268     return readlink ((const char *) pathname, (char *)buf, bufsiz);
269 #else
270     /* XXX: this function is only used for FcConfigRealFilename() so far
271      * and returning -1 as an error still just works.
272      */
273     errno = ENOSYS;
274     return -1;
275 #endif
276 }
277
278 #define __fccompat__
279 #include "fcaliastail.h"
280 #undef __fccompat__