fccompat.c revision c9710b42
1c9710b42Smrg/*
2c9710b42Smrg * fontconfig/src/fccompat.c
3c9710b42Smrg *
4c9710b42Smrg * Copyright © 2012 Red Hat, Inc.
5c9710b42Smrg *
6c9710b42Smrg * Author(s):
7c9710b42Smrg *  Akira TAGOH
8c9710b42Smrg *
9c9710b42Smrg * Permission to use, copy, modify, distribute, and sell this software and its
10c9710b42Smrg * documentation for any purpose is hereby granted without fee, provided that
11c9710b42Smrg * the above copyright notice appear in all copies and that both that
12c9710b42Smrg * copyright notice and this permission notice appear in supporting
13c9710b42Smrg * documentation, and that the name of the author(s) not be used in
14c9710b42Smrg * advertising or publicity pertaining to distribution of the software without
15c9710b42Smrg * specific, written prior permission.  The authors make no
16c9710b42Smrg * representations about the suitability of this software for any purpose.  It
17c9710b42Smrg * is provided "as is" without express or implied warranty.
18c9710b42Smrg *
19c9710b42Smrg * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20c9710b42Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
21c9710b42Smrg * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22c9710b42Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
23c9710b42Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24c9710b42Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25c9710b42Smrg * PERFORMANCE OF THIS SOFTWARE.
26c9710b42Smrg */
27c9710b42Smrg
28c9710b42Smrg#ifdef HAVE_CONFIG_H
29c9710b42Smrg#include "config.h"
30c9710b42Smrg#endif
31c9710b42Smrg
32c9710b42Smrg#include "fcint.h"
33c9710b42Smrg
34c9710b42Smrg#include <errno.h>
35c9710b42Smrg#if HAVE_SYS_TYPES_H
36c9710b42Smrg#include <sys/types.h>
37c9710b42Smrg#endif
38c9710b42Smrg#if HAVE_SYS_STAT_H
39c9710b42Smrg#include <sys/stat.h>
40c9710b42Smrg#endif
41c9710b42Smrg#if HAVE_FCNTL_H
42c9710b42Smrg#include <fcntl.h>
43c9710b42Smrg#endif
44c9710b42Smrg#include <stdarg.h>
45c9710b42Smrg#include <stdlib.h>
46c9710b42Smrg#include <string.h>
47c9710b42Smrg#include <time.h>
48c9710b42Smrg
49c9710b42Smrg#ifdef O_CLOEXEC
50c9710b42Smrg#define FC_O_CLOEXEC O_CLOEXEC
51c9710b42Smrg#else
52c9710b42Smrg#define FC_O_CLOEXEC 0
53c9710b42Smrg#endif
54c9710b42Smrg#ifdef O_LARGEFILE
55c9710b42Smrg#define FC_O_LARGEFILE O_LARGEFILE
56c9710b42Smrg#else
57c9710b42Smrg#define FC_O_LARGEFILE 0
58c9710b42Smrg#endif
59c9710b42Smrg#ifdef O_BINARY
60c9710b42Smrg#define FC_O_BINARY O_BINARY
61c9710b42Smrg#else
62c9710b42Smrg#define FC_O_BINARY 0
63c9710b42Smrg#endif
64c9710b42Smrg#ifdef O_TEMPORARY
65c9710b42Smrg#define FC_O_TEMPORARY O_TEMPORARY
66c9710b42Smrg#else
67c9710b42Smrg#define FC_O_TEMPORARY 0
68c9710b42Smrg#endif
69c9710b42Smrg#ifdef O_NOINHERIT
70c9710b42Smrg#define FC_O_NOINHERIT O_NOINHERIT
71c9710b42Smrg#else
72c9710b42Smrg#define FC_O_NOINHERIT 0
73c9710b42Smrg#endif
74c9710b42Smrg
75c9710b42Smrg#if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
76c9710b42Smrgstatic int
77c9710b42Smrgmkstemp (char *template)
78c9710b42Smrg{
79c9710b42Smrg    static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
80c9710b42Smrg    int fd, i;
81c9710b42Smrg    size_t l;
82c9710b42Smrg
83c9710b42Smrg    if (template == NULL)
84c9710b42Smrg    {
85c9710b42Smrg	errno = EINVAL;
86c9710b42Smrg	return -1;
87c9710b42Smrg    }
88c9710b42Smrg    l = strlen (template);
89c9710b42Smrg    if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
90c9710b42Smrg    {
91c9710b42Smrg	errno = EINVAL;
92c9710b42Smrg	return -1;
93c9710b42Smrg    }
94c9710b42Smrg    do
95c9710b42Smrg    {
96c9710b42Smrg	errno = 0;
97c9710b42Smrg	for (i = l - 6; i < l; i++)
98c9710b42Smrg	{
99c9710b42Smrg	    int r = FcRandom ();
100c9710b42Smrg	    template[i] = s[r % 62];
101c9710b42Smrg	}
102c9710b42Smrg	fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
103c9710b42Smrg    } while (fd < 0 && errno == EEXIST);
104c9710b42Smrg    if (fd >= 0)
105c9710b42Smrg	errno = 0;
106c9710b42Smrg
107c9710b42Smrg    return fd;
108c9710b42Smrg}
109c9710b42Smrg#define HAVE_MKSTEMP 1
110c9710b42Smrg#endif
111c9710b42Smrg
112c9710b42Smrgint
113c9710b42SmrgFcOpen(const char *pathname, int flags, ...)
114c9710b42Smrg{
115c9710b42Smrg    int fd = -1;
116c9710b42Smrg
117c9710b42Smrg    if (flags & O_CREAT)
118c9710b42Smrg    {
119c9710b42Smrg	va_list ap;
120c9710b42Smrg	mode_t mode;
121c9710b42Smrg
122c9710b42Smrg	va_start(ap, flags);
123c9710b42Smrg	mode = (mode_t) va_arg(ap, int);
124c9710b42Smrg	va_end(ap);
125c9710b42Smrg
126c9710b42Smrg	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
127c9710b42Smrg    }
128c9710b42Smrg    else
129c9710b42Smrg    {
130c9710b42Smrg	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
131c9710b42Smrg    }
132c9710b42Smrg
133c9710b42Smrg    return fd;
134c9710b42Smrg}
135c9710b42Smrg
136c9710b42Smrgint
137c9710b42SmrgFcMakeTempfile (char *template)
138c9710b42Smrg{
139c9710b42Smrg    int fd = -1;
140c9710b42Smrg
141c9710b42Smrg#if HAVE_MKOSTEMP
142c9710b42Smrg    fd = mkostemp (template, FC_O_CLOEXEC);
143c9710b42Smrg#elif HAVE_MKSTEMP
144c9710b42Smrg    fd = mkstemp (template);
145c9710b42Smrg#  ifdef F_DUPFD_CLOEXEC
146c9710b42Smrg    if (fd != -1)
147c9710b42Smrg    {
148c9710b42Smrg	int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
149c9710b42Smrg
150c9710b42Smrg	close(fd);
151c9710b42Smrg	fd = newfd;
152c9710b42Smrg    }
153c9710b42Smrg#  elif defined(FD_CLOEXEC)
154c9710b42Smrg    if (fd != -1)
155c9710b42Smrg    {
156c9710b42Smrg	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
157c9710b42Smrg    }
158c9710b42Smrg#  endif
159c9710b42Smrg#elif HAVE__MKTEMP_S
160c9710b42Smrg   if (_mktemp_s(template, strlen(template) + 1) != 0)
161c9710b42Smrg       return -1;
162c9710b42Smrg   fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
163c9710b42Smrg#endif
164c9710b42Smrg
165c9710b42Smrg    return fd;
166c9710b42Smrg}
167c9710b42Smrg
168c9710b42Smrgint32_t
169c9710b42SmrgFcRandom(void)
170c9710b42Smrg{
171c9710b42Smrg    int32_t result;
172c9710b42Smrg
173c9710b42Smrg#if HAVE_RANDOM_R
174c9710b42Smrg    static struct random_data fcrandbuf;
175c9710b42Smrg    static char statebuf[256];
176c9710b42Smrg    static FcBool initialized = FcFalse;
177c9710b42Smrg
178c9710b42Smrg    if (initialized != FcTrue)
179c9710b42Smrg    {
180c9710b42Smrg	initstate_r(time(NULL), statebuf, 256, &fcrandbuf);
181c9710b42Smrg	initialized = FcTrue;
182c9710b42Smrg    }
183c9710b42Smrg
184c9710b42Smrg    random_r(&fcrandbuf, &result);
185c9710b42Smrg#elif HAVE_RANDOM
186c9710b42Smrg    static char statebuf[256];
187c9710b42Smrg    char *state;
188c9710b42Smrg    static FcBool initialized = FcFalse;
189c9710b42Smrg
190c9710b42Smrg    if (initialized != FcTrue)
191c9710b42Smrg    {
192c9710b42Smrg	state = initstate(time(NULL), statebuf, 256);
193c9710b42Smrg	initialized = FcTrue;
194c9710b42Smrg    }
195c9710b42Smrg    else
196c9710b42Smrg	state = setstate(statebuf);
197c9710b42Smrg
198c9710b42Smrg    result = random();
199c9710b42Smrg
200c9710b42Smrg    setstate(state);
201c9710b42Smrg#elif HAVE_LRAND48
202c9710b42Smrg    result = lrand48();
203c9710b42Smrg#elif HAVE_RAND_R
204c9710b42Smrg    static unsigned int seed = time(NULL);
205c9710b42Smrg
206c9710b42Smrg    result = rand_r(&seed);
207c9710b42Smrg#elif HAVE_RAND
208c9710b42Smrg    static FcBool initialized = FcFalse;
209c9710b42Smrg
210c9710b42Smrg    if (initialized != FcTrue)
211c9710b42Smrg    {
212c9710b42Smrg	srand(time(NULL));
213c9710b42Smrg	initialized = FcTrue;
214c9710b42Smrg    }
215c9710b42Smrg    result = rand();
216c9710b42Smrg#else
217c9710b42Smrg# error no random number generator function available.
218c9710b42Smrg#endif
219c9710b42Smrg
220c9710b42Smrg    return result;
221c9710b42Smrg}
222