fccompat.c revision c9710b42
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#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "fcint.h"
33
34#include <errno.h>
35#if HAVE_SYS_TYPES_H
36#include <sys/types.h>
37#endif
38#if HAVE_SYS_STAT_H
39#include <sys/stat.h>
40#endif
41#if HAVE_FCNTL_H
42#include <fcntl.h>
43#endif
44#include <stdarg.h>
45#include <stdlib.h>
46#include <string.h>
47#include <time.h>
48
49#ifdef O_CLOEXEC
50#define FC_O_CLOEXEC O_CLOEXEC
51#else
52#define FC_O_CLOEXEC 0
53#endif
54#ifdef O_LARGEFILE
55#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#if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
76static int
77mkstemp (char *template)
78{
79    static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
80    int fd, i;
81    size_t l;
82
83    if (template == NULL)
84    {
85	errno = EINVAL;
86	return -1;
87    }
88    l = strlen (template);
89    if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
90    {
91	errno = EINVAL;
92	return -1;
93    }
94    do
95    {
96	errno = 0;
97	for (i = l - 6; i < l; i++)
98	{
99	    int r = FcRandom ();
100	    template[i] = s[r % 62];
101	}
102	fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
103    } while (fd < 0 && errno == EEXIST);
104    if (fd >= 0)
105	errno = 0;
106
107    return fd;
108}
109#define HAVE_MKSTEMP 1
110#endif
111
112int
113FcOpen(const char *pathname, int flags, ...)
114{
115    int fd = -1;
116
117    if (flags & O_CREAT)
118    {
119	va_list ap;
120	mode_t mode;
121
122	va_start(ap, flags);
123	mode = (mode_t) va_arg(ap, int);
124	va_end(ap);
125
126	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
127    }
128    else
129    {
130	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
131    }
132
133    return fd;
134}
135
136int
137FcMakeTempfile (char *template)
138{
139    int fd = -1;
140
141#if HAVE_MKOSTEMP
142    fd = mkostemp (template, FC_O_CLOEXEC);
143#elif HAVE_MKSTEMP
144    fd = mkstemp (template);
145#  ifdef F_DUPFD_CLOEXEC
146    if (fd != -1)
147    {
148	int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
149
150	close(fd);
151	fd = newfd;
152    }
153#  elif defined(FD_CLOEXEC)
154    if (fd != -1)
155    {
156	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
157    }
158#  endif
159#elif HAVE__MKTEMP_S
160   if (_mktemp_s(template, strlen(template) + 1) != 0)
161       return -1;
162   fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
163#endif
164
165    return fd;
166}
167
168int32_t
169FcRandom(void)
170{
171    int32_t result;
172
173#if HAVE_RANDOM_R
174    static struct random_data fcrandbuf;
175    static char statebuf[256];
176    static FcBool initialized = FcFalse;
177
178    if (initialized != FcTrue)
179    {
180	initstate_r(time(NULL), statebuf, 256, &fcrandbuf);
181	initialized = FcTrue;
182    }
183
184    random_r(&fcrandbuf, &result);
185#elif HAVE_RANDOM
186    static char statebuf[256];
187    char *state;
188    static FcBool initialized = FcFalse;
189
190    if (initialized != FcTrue)
191    {
192	state = initstate(time(NULL), statebuf, 256);
193	initialized = FcTrue;
194    }
195    else
196	state = setstate(statebuf);
197
198    result = random();
199
200    setstate(state);
201#elif HAVE_LRAND48
202    result = lrand48();
203#elif HAVE_RAND_R
204    static unsigned int seed = time(NULL);
205
206    result = rand_r(&seed);
207#elif HAVE_RAND
208    static FcBool initialized = FcFalse;
209
210    if (initialized != FcTrue)
211    {
212	srand(time(NULL));
213	initialized = FcTrue;
214    }
215    result = rand();
216#else
217# error no random number generator function available.
218#endif
219
220    return result;
221}
222