fccompat.c revision 953daeba
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)
72static int
73mkstemp (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
108int
109FcOpen(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
132int
133FcMakeTempfile (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
164int32_t
165FcRandom(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#ifdef _AIX
174    static char *retval;
175    long res;
176#endif
177
178    if (initialized != FcTrue)
179    {
180#ifdef _AIX
181	initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf);
182#else
183	initstate_r (time (NULL), statebuf, 256, &fcrandbuf);
184#endif
185	initialized = FcTrue;
186    }
187
188#ifdef _AIX
189    random_r (&res, &fcrandbuf);
190    result = (int32_t)res;
191#else
192    random_r (&fcrandbuf, &result);
193#endif
194#elif HAVE_RANDOM
195    static char statebuf[256];
196    char *state;
197    static FcBool initialized = FcFalse;
198
199    if (initialized != FcTrue)
200    {
201	state = initstate (time (NULL), statebuf, 256);
202	initialized = FcTrue;
203    }
204    else
205	state = setstate (statebuf);
206
207    result = random ();
208
209    setstate (state);
210#elif HAVE_LRAND48
211    result = lrand48 ();
212#elif HAVE_RAND_R
213    static unsigned int seed = time (NULL);
214
215    result = rand_r (&seed);
216#elif HAVE_RAND
217    static FcBool initialized = FcFalse;
218
219    if (initialized != FcTrue)
220    {
221	srand (time (NULL));
222	initialized = FcTrue;
223    }
224    result = rand ();
225#else
226# error no random number generator function available.
227#endif
228
229    return result;
230}
231
232#ifdef _WIN32
233#include <direct.h>
234#define mkdir(path,mode) _mkdir(path)
235#endif
236
237FcBool
238FcMakeDirectory (const FcChar8 *dir)
239{
240    FcChar8 *parent;
241    FcBool  ret;
242
243    if (strlen ((char *) dir) == 0)
244	return FcFalse;
245
246    parent = FcStrDirname (dir);
247    if (!parent)
248	return FcFalse;
249    if (access ((char *) parent, F_OK) == 0)
250	ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
251    else if (access ((char *) parent, F_OK) == -1)
252	ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
253    else
254	ret = FcFalse;
255    FcStrFree (parent);
256    return ret;
257}
258
259#define __fccompat__
260#include "fcaliastail.h"
261#undef __fccompat__
262