fccompat.c revision 953daeba
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#include "fcint.h"
29c9710b42Smrg
30c9710b42Smrg#include <errno.h>
31c9710b42Smrg#if HAVE_SYS_TYPES_H
32c9710b42Smrg#include <sys/types.h>
33c9710b42Smrg#endif
34c9710b42Smrg#if HAVE_SYS_STAT_H
35c9710b42Smrg#include <sys/stat.h>
36c9710b42Smrg#endif
37c9710b42Smrg#if HAVE_FCNTL_H
38c9710b42Smrg#include <fcntl.h>
39c9710b42Smrg#endif
40c9710b42Smrg#include <stdarg.h>
41c9710b42Smrg#include <stdlib.h>
42c9710b42Smrg#include <string.h>
43c9710b42Smrg#include <time.h>
44c9710b42Smrg
45c9710b42Smrg#ifdef O_CLOEXEC
46c9710b42Smrg#define FC_O_CLOEXEC O_CLOEXEC
47c9710b42Smrg#else
48c9710b42Smrg#define FC_O_CLOEXEC 0
49c9710b42Smrg#endif
50c9710b42Smrg#ifdef O_LARGEFILE
51c9710b42Smrg#define FC_O_LARGEFILE O_LARGEFILE
52c9710b42Smrg#else
53c9710b42Smrg#define FC_O_LARGEFILE 0
54c9710b42Smrg#endif
55c9710b42Smrg#ifdef O_BINARY
56c9710b42Smrg#define FC_O_BINARY O_BINARY
57c9710b42Smrg#else
58c9710b42Smrg#define FC_O_BINARY 0
59c9710b42Smrg#endif
60c9710b42Smrg#ifdef O_TEMPORARY
61c9710b42Smrg#define FC_O_TEMPORARY O_TEMPORARY
62c9710b42Smrg#else
63c9710b42Smrg#define FC_O_TEMPORARY 0
64c9710b42Smrg#endif
65c9710b42Smrg#ifdef O_NOINHERIT
66c9710b42Smrg#define FC_O_NOINHERIT O_NOINHERIT
67c9710b42Smrg#else
68c9710b42Smrg#define FC_O_NOINHERIT 0
69c9710b42Smrg#endif
70c9710b42Smrg
71c9710b42Smrg#if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
72c9710b42Smrgstatic int
73c9710b42Smrgmkstemp (char *template)
74c9710b42Smrg{
75c9710b42Smrg    static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
76c9710b42Smrg    int fd, i;
77c9710b42Smrg    size_t l;
78c9710b42Smrg
79c9710b42Smrg    if (template == NULL)
80c9710b42Smrg    {
81c9710b42Smrg	errno = EINVAL;
82c9710b42Smrg	return -1;
83c9710b42Smrg    }
84c9710b42Smrg    l = strlen (template);
85c9710b42Smrg    if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
86c9710b42Smrg    {
87c9710b42Smrg	errno = EINVAL;
88c9710b42Smrg	return -1;
89c9710b42Smrg    }
90c9710b42Smrg    do
91c9710b42Smrg    {
92c9710b42Smrg	errno = 0;
93c9710b42Smrg	for (i = l - 6; i < l; i++)
94c9710b42Smrg	{
95c9710b42Smrg	    int r = FcRandom ();
96c9710b42Smrg	    template[i] = s[r % 62];
97c9710b42Smrg	}
98c9710b42Smrg	fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
99c9710b42Smrg    } while (fd < 0 && errno == EEXIST);
100c9710b42Smrg    if (fd >= 0)
101c9710b42Smrg	errno = 0;
102c9710b42Smrg
103c9710b42Smrg    return fd;
104c9710b42Smrg}
105c9710b42Smrg#define HAVE_MKSTEMP 1
106c9710b42Smrg#endif
107c9710b42Smrg
108c9710b42Smrgint
109c9710b42SmrgFcOpen(const char *pathname, int flags, ...)
110c9710b42Smrg{
111c9710b42Smrg    int fd = -1;
112c9710b42Smrg
113c9710b42Smrg    if (flags & O_CREAT)
114c9710b42Smrg    {
115c9710b42Smrg	va_list ap;
116c9710b42Smrg	mode_t mode;
117c9710b42Smrg
118c9710b42Smrg	va_start(ap, flags);
119c9710b42Smrg	mode = (mode_t) va_arg(ap, int);
120c9710b42Smrg	va_end(ap);
121c9710b42Smrg
122c9710b42Smrg	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
123c9710b42Smrg    }
124c9710b42Smrg    else
125c9710b42Smrg    {
126c9710b42Smrg	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
127c9710b42Smrg    }
128c9710b42Smrg
129c9710b42Smrg    return fd;
130c9710b42Smrg}
131c9710b42Smrg
132c9710b42Smrgint
133c9710b42SmrgFcMakeTempfile (char *template)
134c9710b42Smrg{
135c9710b42Smrg    int fd = -1;
136c9710b42Smrg
137c9710b42Smrg#if HAVE_MKOSTEMP
138c9710b42Smrg    fd = mkostemp (template, FC_O_CLOEXEC);
139c9710b42Smrg#elif HAVE_MKSTEMP
140c9710b42Smrg    fd = mkstemp (template);
141c9710b42Smrg#  ifdef F_DUPFD_CLOEXEC
142c9710b42Smrg    if (fd != -1)
143c9710b42Smrg    {
144c9710b42Smrg	int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
145c9710b42Smrg
146c9710b42Smrg	close(fd);
147c9710b42Smrg	fd = newfd;
148c9710b42Smrg    }
149c9710b42Smrg#  elif defined(FD_CLOEXEC)
150c9710b42Smrg    if (fd != -1)
151c9710b42Smrg    {
152c9710b42Smrg	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
153c9710b42Smrg    }
154c9710b42Smrg#  endif
155c9710b42Smrg#elif HAVE__MKTEMP_S
156c9710b42Smrg   if (_mktemp_s(template, strlen(template) + 1) != 0)
157c9710b42Smrg       return -1;
158c9710b42Smrg   fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
159c9710b42Smrg#endif
160c9710b42Smrg
161c9710b42Smrg    return fd;
162c9710b42Smrg}
163c9710b42Smrg
164c9710b42Smrgint32_t
165c9710b42SmrgFcRandom(void)
166c9710b42Smrg{
167c9710b42Smrg    int32_t result;
168c9710b42Smrg
169c9710b42Smrg#if HAVE_RANDOM_R
170c9710b42Smrg    static struct random_data fcrandbuf;
171c9710b42Smrg    static char statebuf[256];
172c9710b42Smrg    static FcBool initialized = FcFalse;
173b09479dcSmrg#ifdef _AIX
174b09479dcSmrg    static char *retval;
175b09479dcSmrg    long res;
176b09479dcSmrg#endif
177c9710b42Smrg
178c9710b42Smrg    if (initialized != FcTrue)
179c9710b42Smrg    {
180b09479dcSmrg#ifdef _AIX
181b09479dcSmrg	initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf);
182b09479dcSmrg#else
183b09479dcSmrg	initstate_r (time (NULL), statebuf, 256, &fcrandbuf);
184b09479dcSmrg#endif
185c9710b42Smrg	initialized = FcTrue;
186c9710b42Smrg    }
187c9710b42Smrg
188b09479dcSmrg#ifdef _AIX
189b09479dcSmrg    random_r (&res, &fcrandbuf);
190b09479dcSmrg    result = (int32_t)res;
191b09479dcSmrg#else
192b09479dcSmrg    random_r (&fcrandbuf, &result);
193b09479dcSmrg#endif
194c9710b42Smrg#elif HAVE_RANDOM
195c9710b42Smrg    static char statebuf[256];
196c9710b42Smrg    char *state;
197c9710b42Smrg    static FcBool initialized = FcFalse;
198c9710b42Smrg
199c9710b42Smrg    if (initialized != FcTrue)
200c9710b42Smrg    {
201b09479dcSmrg	state = initstate (time (NULL), statebuf, 256);
202c9710b42Smrg	initialized = FcTrue;
203c9710b42Smrg    }
204c9710b42Smrg    else
205b09479dcSmrg	state = setstate (statebuf);
206c9710b42Smrg
207b09479dcSmrg    result = random ();
208c9710b42Smrg
209b09479dcSmrg    setstate (state);
210c9710b42Smrg#elif HAVE_LRAND48
211b09479dcSmrg    result = lrand48 ();
212c9710b42Smrg#elif HAVE_RAND_R
213b09479dcSmrg    static unsigned int seed = time (NULL);
214c9710b42Smrg
215b09479dcSmrg    result = rand_r (&seed);
216c9710b42Smrg#elif HAVE_RAND
217c9710b42Smrg    static FcBool initialized = FcFalse;
218c9710b42Smrg
219c9710b42Smrg    if (initialized != FcTrue)
220c9710b42Smrg    {
221b09479dcSmrg	srand (time (NULL));
222c9710b42Smrg	initialized = FcTrue;
223c9710b42Smrg    }
224b09479dcSmrg    result = rand ();
225c9710b42Smrg#else
226c9710b42Smrg# error no random number generator function available.
227c9710b42Smrg#endif
228c9710b42Smrg
229c9710b42Smrg    return result;
230c9710b42Smrg}
2316fc018e4Smrg
2326fc018e4Smrg#ifdef _WIN32
2336fc018e4Smrg#include <direct.h>
2346fc018e4Smrg#define mkdir(path,mode) _mkdir(path)
2356fc018e4Smrg#endif
2366fc018e4Smrg
2376fc018e4SmrgFcBool
2386fc018e4SmrgFcMakeDirectory (const FcChar8 *dir)
2396fc018e4Smrg{
2406fc018e4Smrg    FcChar8 *parent;
2416fc018e4Smrg    FcBool  ret;
2426fc018e4Smrg
2436fc018e4Smrg    if (strlen ((char *) dir) == 0)
2446fc018e4Smrg	return FcFalse;
2456fc018e4Smrg
2466fc018e4Smrg    parent = FcStrDirname (dir);
2476fc018e4Smrg    if (!parent)
2486fc018e4Smrg	return FcFalse;
2496fc018e4Smrg    if (access ((char *) parent, F_OK) == 0)
2506fc018e4Smrg	ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
2516fc018e4Smrg    else if (access ((char *) parent, F_OK) == -1)
2526fc018e4Smrg	ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
2536fc018e4Smrg    else
2546fc018e4Smrg	ret = FcFalse;
2556fc018e4Smrg    FcStrFree (parent);
2566fc018e4Smrg    return ret;
2576fc018e4Smrg}
258953daebaSmrg
259953daebaSmrg#define __fccompat__
260953daebaSmrg#include "fcaliastail.h"
261953daebaSmrg#undef __fccompat__
262