fccompat.c 5.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*
 * fontconfig/src/fccompat.c
 *
 * Copyright © 2012 Red Hat, Inc.
 *
 * Author(s):
 *  Akira TAGOH
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the author(s) not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  The authors make no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include "fcint.h"

30 31 32 33 34 35 36
#include <errno.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
37 38 39
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
40 41 42
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
43 44
#include <stdarg.h>
#include <stdlib.h>
45 46
#include <string.h>
#include <time.h>
47 48 49 50 51 52 53 54 55 56 57

#ifdef O_CLOEXEC
#define FC_O_CLOEXEC O_CLOEXEC
#else
#define FC_O_CLOEXEC 0
#endif
#ifdef O_LARGEFILE
#define FC_O_LARGEFILE O_LARGEFILE
#else
#define FC_O_LARGEFILE 0
#endif
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
#ifdef O_BINARY
#define FC_O_BINARY O_BINARY
#else
#define FC_O_BINARY 0
#endif
#ifdef O_TEMPORARY
#define FC_O_TEMPORARY O_TEMPORARY
#else
#define FC_O_TEMPORARY 0
#endif
#ifdef O_NOINHERIT
#define FC_O_NOINHERIT O_NOINHERIT
#else
#define FC_O_NOINHERIT 0
#endif

#if !defined (HAVE_MKOSTEMP) && !defined(HAVE_MKSTEMP) && !defined(HAVE__MKTEMP_S)
static int
mkstemp (char *template)
{
    static const char s[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int fd, i;
    size_t l;

    if (template == NULL)
    {
	errno = EINVAL;
	return -1;
    }
    l = strlen (template);
    if (l < 6 || strcmp (&template[l - 6], "XXXXXX") != 0)
    {
	errno = EINVAL;
	return -1;
    }
    do
    {
	errno = 0;
	for (i = l - 6; i < l; i++)
	{
	    int r = FcRandom ();
	    template[i] = s[r % 62];
	}
	fd = FcOpen (template, FC_O_BINARY | O_CREAT | O_EXCL | FC_O_TEMPORARY | FC_O_NOINHERIT | O_RDWR, 0600);
    } while (fd < 0 && errno == EEXIST);
    if (fd >= 0)
	errno = 0;

    return fd;
}
#define HAVE_MKSTEMP 1
#endif
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

int
FcOpen(const char *pathname, int flags, ...)
{
    int fd = -1;

    if (flags & O_CREAT)
    {
	va_list ap;
	mode_t mode;

	va_start(ap, flags);
	mode = (mode_t) va_arg(ap, int);
	va_end(ap);

	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE, mode);
    }
    else
    {
	fd = open(pathname, flags | FC_O_CLOEXEC | FC_O_LARGEFILE);
    }

    return fd;
}

int
FcMakeTempfile (char *template)
{
    int fd = -1;

#if HAVE_MKOSTEMP
    fd = mkostemp (template, FC_O_CLOEXEC);
#elif HAVE_MKSTEMP
    fd = mkstemp (template);
#  ifdef F_DUPFD_CLOEXEC
    if (fd != -1)
    {
147
	int newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDIN_FILENO);
148 149 150 151 152 153 154 155 156 157

	close(fd);
	fd = newfd;
    }
#  elif defined(FD_CLOEXEC)
    if (fd != -1)
    {
	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
    }
#  endif
Akira TAGOH's avatar
Akira TAGOH committed
158 159 160 161
#elif HAVE__MKTEMP_S
   if (_mktemp_s(template, strlen(template) + 1) != 0)
       return -1;
   fd = FcOpen(template, O_RDWR | O_EXCL | O_CREAT, 0600);
162 163 164 165
#endif

    return fd;
}
166 167 168 169 170 171 172 173 174 175

int32_t
FcRandom(void)
{
    int32_t result;

#if HAVE_RANDOM_R
    static struct random_data fcrandbuf;
    static char statebuf[256];
    static FcBool initialized = FcFalse;
176 177 178 179
#ifdef _AIX
    static char *retval;
    long res;
#endif
180 181 182

    if (initialized != FcTrue)
    {
183 184 185 186 187
#ifdef _AIX
	initstate_r (time (NULL), statebuf, 256, &retval, &fcrandbuf);
#else
	initstate_r (time (NULL), statebuf, 256, &fcrandbuf);
#endif
188 189 190
	initialized = FcTrue;
    }

191 192 193 194 195 196
#ifdef _AIX
    random_r (&res, &fcrandbuf);
    result = (int32_t)res;
#else
    random_r (&fcrandbuf, &result);
#endif
197 198 199 200 201 202 203
#elif HAVE_RANDOM
    static char statebuf[256];
    char *state;
    static FcBool initialized = FcFalse;

    if (initialized != FcTrue)
    {
204
	state = initstate (time (NULL), statebuf, 256);
205 206 207
	initialized = FcTrue;
    }
    else
208
	state = setstate (statebuf);
209

210
    result = random ();
211

212
    setstate (state);
213
#elif HAVE_LRAND48
214
    result = lrand48 ();
215
#elif HAVE_RAND_R
216
    static unsigned int seed = time (NULL);
217

218
    result = rand_r (&seed);
219 220 221 222 223
#elif HAVE_RAND
    static FcBool initialized = FcFalse;

    if (initialized != FcTrue)
    {
224
	srand (time (NULL));
225 226
	initialized = FcTrue;
    }
227
    result = rand ();
228 229 230 231 232 233
#else
# error no random number generator function available.
#endif

    return result;
}
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

#ifdef _WIN32
#include <direct.h>
#define mkdir(path,mode) _mkdir(path)
#endif

FcBool
FcMakeDirectory (const FcChar8 *dir)
{
    FcChar8 *parent;
    FcBool  ret;

    if (strlen ((char *) dir) == 0)
	return FcFalse;

    parent = FcStrDirname (dir);
    if (!parent)
	return FcFalse;
    if (access ((char *) parent, F_OK) == 0)
	ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0;
    else if (access ((char *) parent, F_OK) == -1)
	ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0;
    else
	ret = FcFalse;
    FcStrFree (parent);
    return ret;
}
261

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
ssize_t
FcReadLink (const FcChar8 *pathname,
	    FcChar8       *buf,
	    size_t         bufsiz)
{
#ifdef HAVE_READLINK
    return readlink ((const char *) pathname, (char *)buf, bufsiz);
#else
    /* XXX: this function is only used for FcConfigRealFilename() so far
     * and returning -1 as an error still just works.
     */
    errno = ENOSYS;
    return -1;
#endif
}

278 279 280
#define __fccompat__
#include "fcaliastail.h"
#undef __fccompat__