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