Fix inversion between Tinos and Cousine in the comment
[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 #include <stdarg.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <time.h>
44
45 #ifdef O_CLOEXEC
46 #define FC_O_CLOEXEC O_CLOEXEC
47 #else
48 #define FC_O_CLOEXEC 0
49 #endif
50 #ifdef O_LARGEFILE
51 #define FC_O_LARGEFILE O_LARGEFILE
52 #else
53 #define FC_O_LARGEFILE 0
54 #endif
55 #ifdef O_BINARY
56 #define FC_O_BINARY O_BINARY
57 #else
58 #define FC_O_BINARY 0
59 #endif
60 #ifdef O_TEMPORARY
61 #define FC_O_TEMPORARY O_TEMPORARY
62 #else
63 #define FC_O_TEMPORARY 0
64 #endif
65 #ifdef O_NOINHERIT
66 #define FC_O_NOINHERIT O_NOINHERIT
67 #else
68 #define FC_O_NOINHERIT 0
69 #endif
70
71 #if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
72 static int
73 mkstemp (char *template)
74 {
75     static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
76     int fd, i;
77     size_t l;
78
79     if (template == NULL)
80     {
81         errno = EINVAL;
82         return -1;
83     }
84     l = strlen (template);
85     if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
86     {
87         errno = EINVAL;
88         return -1;
89     }
90     do
91     {
92         errno = 0;
93         for (i = l - 6; i < l; i++)
94         {
95             int r = FcRandom ();
96             template[i] = s[r % 62];
97         }
98         fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
99     } while (fd < 0 && errno == EEXIST);
100     if (fd >= 0)
101         errno = 0;
102
103     return fd;
104 }
105 #define HAVE_MKSTEMP 1
106 #endif
107
108 int
109 FcOpen(const char *pathname, int flags, ...)
110 {
111     int fd = -1;
112
113     if (flags & O_CREAT)
114     {
115         va_list ap;
116         mode_t mode;
117
118         va_start(ap, flags);
119         mode = (mode_t) va_arg(ap, int);
120         va_end(ap);
121
122         fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
123     }
124     else
125     {
126         fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
127     }
128
129     return fd;
130 }
131
132 int
133 FcMakeTempfile (char *template)
134 {
135     int fd = -1;
136
137 #if HAVE_MKOSTEMP
138     fd = mkostemp (template, FC_O_CLOEXEC);
139 #elif HAVE_MKSTEMP
140     fd = mkstemp (template);
141 #  ifdef F_DUPFD_CLOEXEC
142     if (fd != -1)
143     {
144         int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
145
146         close(fd);
147         fd = newfd;
148     }
149 #  elif defined(FD_CLOEXEC)
150     if (fd != -1)
151     {
152         fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
153     }
154 #  endif
155 #elif HAVE__MKTEMP_S
156    if (_mktemp_s(template, strlen(template) + 1) != 0)
157        return -1;
158    fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
159 #endif
160
161     return fd;
162 }
163
164 int32_t
165 FcRandom(void)
166 {
167     int32_t result;
168
169 #if HAVE_RANDOM_R
170     static struct random_data fcrandbuf;
171     static char statebuf[256];
172     static FcBool initialized = FcFalse;
173
174     if (initialized != FcTrue)
175     {
176         initstate_r(time(NULL), statebuf, 256, &fcrandbuf);
177         initialized = FcTrue;
178     }
179
180     random_r(&fcrandbuf, &result);
181 #elif HAVE_RANDOM
182     static char statebuf[256];
183     char *state;
184     static FcBool initialized = FcFalse;
185
186     if (initialized != FcTrue)
187     {
188         state = initstate(time(NULL), statebuf, 256);
189         initialized = FcTrue;
190     }
191     else
192         state = setstate(statebuf);
193
194     result = random();
195
196     setstate(state);
197 #elif HAVE_LRAND48
198     result = lrand48();
199 #elif HAVE_RAND_R
200     static unsigned int seed = time(NULL);
201
202     result = rand_r(&seed);
203 #elif HAVE_RAND
204     static FcBool initialized = FcFalse;
205
206     if (initialized != FcTrue)
207     {
208         srand(time(NULL));
209         initialized = FcTrue;
210     }
211     result = rand();
212 #else
213 # error no random number generator function available.
214 #endif
215
216     return result;
217 }
218
219 #ifdef _WIN32
220 #include <direct.h>
221 #define mkdir(path,mode) _mkdir(path)
222 #endif
223
224 FcBool
225 FcMakeDirectory (const FcChar8 *dir)
226 {
227     FcChar8 *parent;
228     FcBool  ret;
229
230     if (strlen ((char *) dir) == 0)
231         return FcFalse;
232
233     parent = FcStrDirname (dir);
234     if (!parent)
235         return FcFalse;
236     if (access ((char *) parent, F_OK) == 0)
237         ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
238     else if (access ((char *) parent, F_OK) == -1)
239         ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
240     else
241         ret = FcFalse;
242     FcStrFree (parent);
243     return ret;
244 }