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