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